推荐一款优雅的日历控件
项目需要用到日历控件,这是我们的效果图。
去github上搜了一哈,搜到大神写的CalendarView
,各种炫酷效果,我这种的也只需要自定义效果就可以了,话不多说,直接开撸!
这里附上github的链接地址:https://github.com/huanghaibin-dev/CalendarView, 里面的api文档说明还是很齐全的,这里就直接记录我的开发历程。
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() { @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 拉你入群。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Android 进阶自定义View(5)图表统计PieChartView圆饼图的实现
今天讲图表统计中比较常用的一个,像支付宝的月账单啥的,都是用圆饼图来做数据统计的,先看一下我最终实现的效果图: image.png 该效果实际上是两个实心圆叠加后的效果。 image.png image.png 《一》View实现思路分析: (1)根据占比集合数据,计算所需绘制的角度,动态设置画笔颜色,drawArc()绘制外圆弧 (2)drawCircle()绘制内圆 (3)确定每块圆饼的小白点的位置 (4)绘制白点的沿线和占比文字 《二》具体实现: (1)绘制不同颜色的圆饼 for (int i = 0; i < mRateList.size(); i++) { mPaint.setStyle(Paint.Style.FILL); mPaint.setColor(mColorList.get(i)); // Log.e("TAG", "startAngle=" + startAngle + "--sweepAngle=" + ((int) (mRateList.get(i) * (360)) - offset)); canvas.drawArc(rectF, startAng...
- 下一篇
Android绘制(二):来用Path绘出想要的图形吧!
Android绘制(一):来用shape绘出想要的图形吧! 目录 前言 绘制线 绘制图形 绘制弧 绘制文字 组合 贝塞尔曲线 最后 前言 之前有一篇用shape进行绘制的, 但是那个偏向静态, path结合属性动画可以动起来哦~ path是什么? 来看看官方的介绍: The Path class encapsulates compound (multiple contour) geometric paths consisting of straight line segments, quadratic curves, and cubic curves. It can be drawn with canvas.drawPath(path, paint), either filled or stroked (based on the paint's Style), or it can be used for clipping or to draw text on a path. 咕果翻译一下就是: Path类封装了由直线段,二次曲线和三次曲线组成的复合(多个轮廓)几何路径。 它可以使用ca...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS7安装Docker,走上虚拟化容器引擎之路
- CentOS7设置SWAP分区,小内存服务器的救世主
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS7,8上快速安装Gitea,搭建Git服务器
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2全家桶,快速入门学习开发网站教程
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装