推荐一款优雅的日历控件

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了推荐一款优雅的日历控件相关的知识,希望对你有一定的参考价值。

项目需要用到日历控件,这是我们的效果图。??

技术分享图片

去github上搜了一哈,搜到大神写的CalendarView,各种炫酷效果,我这种的也只需要自定义效果就可以了,话不多说,直接开撸! ??

gradle 关联

implementation ‘com.haibin:calendarview:3.4.0‘

使用

刚开始布局中使用的话注意是?<com.haibin.calendarview.CalendarView />?有包名路径的,如果直接是?<CalendarView />?使用的是系统自带的日历控件。

<com.haibin.calendarview.CalendarView
????android:layout_width="match_parent"
????android:layout_height="wrap_content"?/>

可以直接预览效果,一些属性配置项: ??
app:month_view_show_mode="mode_fix"??配置月视图的显示模式 ?
app:current_month_text_color="#212121"??当前页月份的月字体颜色 ?
app:other_month_text_color="#cccccc"?当前页其余月份的月字体颜色 ? ?
等等一系列的属性配置,文档里都是有的。当然要实现自己的效果,那些属性是不够的,需要我们自定义MonthView 去实现(项目地址里也有demo可下载参考)。

自定义 MonthView

自定义MyMonthView?类继承自?MonthView,xml布局里添加属性?app:month_view="com.calendar.MyMonthView",这里的路径是自己实际项目中的monthView的路径,需要我们自己去绘制日历。

//取消日历字体加粗
mCurMonthTextPaint.setFakeBoldText(false);
mOtherMonthTextPaint.setFakeBoldText(false);

这里插个题外的知识点tip:?setFakeBoldText(true)??的加粗效果比?android:textStyle="bold"?属性的加粗效果要弱点,就是不会太粗,又比细稍微粗一点的效果~ 了解一下

onDrawText里进行绘制,正常样式的日历可正常显示时间的

@Override
protected?void?onDrawText(Canvas?canvas,?Calendar?calendar,?int?x,?int?y,?boolean?hasScheme,?boolean?isSelected)?{
????float?baselineY?=?mTextBaseLine?+?y;
????int?cx?=?x?+?mItemWidth?/?2;
????int?cy?=?y?+?mItemHeight?/?2;
????canvas.drawText(String.valueOf(calendar.getDay()),?cx,?baselineY,?calendar.isCurrentMonth()???mCurMonthTextPaint?:?mOtherMonthTextPaint);
}

这里要分类下我们需要几种类型的样式: ?

技术分享图片

?1、不可完成的

技术分享图片

2、可以完成的

技术分享图片

3、今日已完成的

技术分享图片

4、历史已完成的

模拟数据,通过scheme 标记区分各样式

Calendar?calendar1?=?getSchemeCalendar(2018,?8,?11,?"1");
Calendar?calendar2?=?getSchemeCalendar(2018,?8,?12,?"2");
Calendar?calendar3?=?getSchemeCalendar(2018,?8,?13,?"3");
Calendar?calendar4?=?getSchemeCalendar(2018,?8,?6,?"4");

map.put(calendar1.toString(),?calendar1);
map.put(calendar2.toString(),?calendar2);
map.put(calendar3.toString(),?calendar3);
map.put(calendar4.toString(),?calendar4);
calendarView.setSchemeDate(map);

private?Calendar?getSchemeCalendar(int?year,?int?month,?int?day,?String?text)?{
????Calendar?calendar?=?new?Calendar();
????calendar.setYear(year);
????calendar.setMonth(month);
????calendar.setDay(day);
????calendar.setScheme(text);
????return?calendar;
}

初始化两个paint,有两张图片资源的用Bitmap去绘制

paint1.setColor(ContextCompat.getColor(context,?R.color.green));
paint1.setTextSize(DensityUtil.spToPx(context,?13));
paint1.setStyle(Paint.Style.STROKE);
paint1.setAntiAlias(true);
paint1.setTextAlign(Paint.Align.CENTER);

paint2.setColor(ContextCompat.getColor(context,?R.color.white));
paint2.setTextSize(DensityUtil.spToPx(context,?13));
paint2.setAntiAlias(true);
paint2.setTextAlign(Paint.Align.CENTER);

dayBgBitmap?=?BitmapFactory.decodeResource(getResources(),?R.mipmap.day_bg);
daySuccessBitmap?=?BitmapFactory.decodeResource(getResources(),?R.mipmap.day_success);

主要的方法 onDrawText ,根据不同scheme 绘制各view

@Override
protected?void?onDrawText(Canvas?canvas,?Calendar?calendar,?int?x,?int?y,?boolean?hasScheme,?boolean?isSelected)?{
????//这里的x、y?是每日的起点坐标
????float?baselineY?=?mTextBaseLine?+?y;
????int?cx?=?x?+?mItemWidth?/?2;
????int?cy?=?y?+?mItemHeight?/?2;
????if?("1".equals(calendar.getScheme()))?{
????????//?不可完成的,绘制圆
????????paint1.setStrokeWidth(0);
????????canvas.drawText(String.valueOf(calendar.getDay()),?cx,?baselineY,?paint1);
????????paint1.setStrokeWidth(DensityUtil.dpToPx(context,?1));
????????canvas.drawCircle(cx,?cy?+?3,?mItemWidth?/?4?-?9,?paint1);
????}?else?if?("2".equals(calendar.getScheme()))?{
????????//可以完成的,绘制背景图
????????canvas.drawText(String.valueOf(calendar.getDay()),?cx,?baselineY,?paint2);
????????canvas.drawBitmap(dayBgBitmap,?x?+?mItemWidth?/?4?-?5,?y?+?mItemHeight?/?4?+?8,?paint2);
????}?else?if?("3".equals(calendar.getScheme()))?{
????????//今日已完成的,绘制圆+打勾图片
????????paint1.setStrokeWidth(0);
????????canvas.drawText(String.valueOf(calendar.getDay()),?cx,?baselineY,?paint1);
????????paint1.setStrokeWidth(DensityUtil.dpToPx(context,?1));
????????canvas.drawCircle(cx,?cy?+?3,?mItemWidth?/?4?-?9,?paint1);
????????canvas.drawBitmap(daySuccessBitmap,?x?+?mItemWidth?*?3?/?4?-?18,?y?+?mItemHeight?*?3?/?4?-?24,?paint1);
????}?else?if?("4".equals(calendar.getScheme()))?{
????????//历史已完成的,绘制打勾图片
????????paint1.setStrokeWidth(0);
????????canvas.drawText(String.valueOf(calendar.getDay()),?cx,?baselineY,?paint1);
????????canvas.drawBitmap(daySuccessBitmap,?x?+?mItemWidth?*?3?/?4?-?18,?y?+?mItemHeight?*?3?/?4?-?40,?paint1);
????}?else?{
????????//正常日期的显示
????????canvas.drawText(String.valueOf(calendar.getDay()),?cx,?baselineY,?calendar.isCurrentMonth()???mCurMonthTextPaint?:?mOtherMonthTextPaint);
????}
}

至此,视图绘制完成。

技术分享图片

接下来完成基本的api调用。

api 调用

初始化赋值当前的年月,日历切换时,时间对应改变。

//初始化当前年月
tvMonth.setText(calendarView.getCurYear()?+?"年"?+?calendarView.getCurMonth()?+?"月");
//月份切换改变事件
calendarView.setOnMonthChangeListener(new?CalendarView.OnMonthChangeListener()?{
[email protected]
????public?void?onMonthChange(int?year,?int?month)?{
????????tvMonth.setText(year?+?"年"?+?month?+?"月");
????}
});

布局里有个时间选择器,用于选择年月的,这里采用的是 Android-PickerView 时间选择器。

//时间选择器选择年月,对应的日历切换到指定日期
picker.setOnClickListener(new?View.OnClickListener()?{
[email protected]
????public?void?onClick(View?v)?{
????????TimePickerView?pvTime?=?new?TimePickerBuilder(MainActivity.this,?new?OnTimeSelectListener()?{
[email protected]
????????????public?void?onTimeSelect(Date?date,?View?v)?{
????????????????java.util.Calendar?c?=?java.util.Calendar.getInstance();
????????????????c.setTime(date);
????????????????int?year?=?c.get(java.util.Calendar.YEAR);
????????????????int?month?=?c.get(java.util.Calendar.MONTH);
????????????????//滚动到指定日期
????????????????calendarView.scrollToCalendar(year,?month?+?1,?1);
????????????}
????????}).setType(type).build();
????????pvTime.show();
????}
});

日期的选择监听事件

calendarView.setOnDateSelectedListener(new?CalendarView.OnDateSelectedListener()?{
[email protected]
????public?void?onDateSelected(Calendar?calendar,?boolean?isClick)?{

????}
});

效果完成图,当然不同项目里的效果图是不一样的,只要会canvas的基本绘制都是可以达到各自想要的效果的。

技术分享图片

详细代码见 可以评论详聊哦?

以上是关于推荐一款优雅的日历控件的主要内容,如果未能解决你的问题,请参考以下文章

jquery日历插件有没有可以标记某一天的,推荐一下

网页日历显示控件calendar3.1

一款清新优雅的中后台模版,内置丰富可配置的主题(强烈推荐)

求一个bootstrap或者jQuery的日历控件

撸一个Android高性能日历控件,高仿魅族

Fullcalendar 日历控件的基本使用