资讯专栏INFORMATION COLUMN

推荐一款优雅的日历控件

fou7 / 1075人阅读

摘要:原文链接项目需要用到日历控件,这是我们的效果图。关联使用刚开始布局中使用的话注意是有包名路径的,如果直接是使用的是系统自带的日历控件。调用初始化赋值当前的年月,日历切换时,时间对应改变。

原文链接:https://mp.weixin.qq.com/s/SmxDiWIidHS2hwVvFcz_hw

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

去github上搜了一哈,搜到大神写的CalendarView,各种炫酷效果,我这种的也只需要自定义效果就可以了,话不多说,直接开撸!
这里附上github的链接地址:https://github.com/huanghaibin-dev/CalendarView, 里面的api文档说明还是很齐全的,这里就直接记录我的开发历程。

gradle 关联

implementation "com.haibin:calendarview:3.4.0"

使用

刚开始布局中使用的话注意是 有包名路径的,如果直接是 使用的是系统自带的日历控件。

可以直接预览效果,一些属性配置项:
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() {
    @Override
    public void onMonthChange(int year, int month) {
        tvMonth.setText(year + "年" + month + "月");
    }
});

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

//时间选择器选择年月,对应的日历切换到指定日期
picker.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        TimePickerView pvTime = new TimePickerBuilder(MainActivity.this, new OnTimeSelectListener() {
            @Override
            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() {
    @Override
    public void onDateSelected(Calendar calendar, boolean isClick) {

    }
});

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

详细代码见
github地址:https://github.com/taixiang/calendar

欢迎关注我的博客:https://blog.manjiexiang.cn/
更多精彩欢迎关注微信号:春风十里不如认识你

有个「佛系码农圈」,欢迎大家加入畅聊,开心就好!

过期了,可加我微信 tx467220125 拉你入群。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/14368.html

相关文章

  • 自定义控件及效果

    摘要:实现炫酷的登录效果美观,动画效果丰富风格底部选择器支持时间,日期,自定义带来一组风格底部选择器控件,虽然我们不提倡安卓使用风格的控件,但是难免有些产品和美工一味追求风格。 Android 动画效果定值范围选择控件 实现固定值的范围选择, 并添加动态效果, 使用方便 项目需求讨论 - Android 自定义 Dialog 实现步骤及封装 根据实际项目需求出发。因为项目中的对话框要配合整个...

    刘德刚 评论0 收藏0
  • 最全面 Material Design 学习资料

    摘要:是以后的主流设计风格,现在已经越来越多的遵循的设计规范来进行开发,是每个开发者必学的基础技术。 本人目前正在找工作,想了解我的详细情况请移步到我的 网页版简历 ,希望能得到各位的推荐,谢谢! 关于 Material Design 在这里我就不在多做介绍了,想必做Android开发的 都听过它的大名 ,甚至用过无数次了。Material Design 是以后 Android 的主流设计风...

    yagami 评论0 收藏0
  • 控件 - 收藏集 - 掘金

    摘要:它也是一款可以帮助你轻松实现侧滑效果的控件掘金一个灵活易用可以帮助开发者实现侧滑效果的开源项目。直接上图站多媒体选择器掘金基于模式的多媒体选择器。 Android 开源库 V - Layout:手把手带你分析 淘宝、天猫都在用的 UI 框架 - Android - 掘金前言 V- Layout 是阿里出品的基础 UI 框架,用于快速实现页面的复杂布局,在手机天猫 Android版 内广...

    sixgo 评论0 收藏0
  • UI仿写

    摘要:像微信一样的图片选择器像微信一样的图片选择器像微信一样录制视频和音频重构史上最牛逼的音乐播放器仿网易云音乐已开源无论是下载模块,还是换肤模块,还是炫丽的界面通讯录顶部固定的索引效果通讯录和城市列表展示时通用的滑动顶部固定的索引列表效果 Android 仿京东、天猫 app 的商品详情页的布局架构, 以及功能实现 仿京东、天猫 app 的商品详情页 自定义 viewgroup+viewd...

    frontoldman 评论0 收藏0
  • 一款基于移动端日历控件iantooDate

    摘要:已被移除过时的提醒时间的颜色。默认当日历控件滑动的时候是否实时更新日历控件的位置主要是对部分低端机型做性能处理。返回当前的时间调用该方法关闭日历控件。年月日时分秒星期 原文链接 使用 引入文件: ./build/css/iantooDate.css ./build/js/iantooDate.js 并在页面上调用: iantoo.date() 详细使用方法见page/iantooDat...

    liangzai_cool 评论0 收藏0

发表评论

0条评论

fou7

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<