最近公司项目需要用到日历来实现某些功能,作为小菜的我首先就想到了去找现有的日历控件,不过朋友推荐说MaterialCalendarView非常非常的强大,于是我又开始了新一轮的“装逼”之路
GitHub链接奉上:https://github.com/prolificinteractive/material-calendarview
强力推荐大家按照GitHub上的文档开发,这里作为小菜的我,喜欢在别人的代码里找找“灵感”,于是乎就直接把他的关键类导入到了自己的项目(顺便说一下,按Module导入问题太多,懒的修改才直接考的源码,有木有很聪明)。先上效果图:
我导入的关键代码是library文件下的main代码和res下的相关代码,非常简单粗暴的操作
接着就是点进去源码的世界里遨游,寻找“灵感”,分析效果图可以大致分为,topbar和下面的viewpager两部分:接下来先来分析大神的topbar代码:进入MaterialCalendarView类里面可以找到相关代码如下图:
private void setupChildren() { topbar = new LinearLayout(getContext()); topbar.setOrientation(LinearLayout.HORIZONTAL); topbar.setClipChildren(false); topbar.setClipToPadding(false); addView(topbar, new LayoutParams(1)); //测试看有没有往右面移动 LinearLayout ll=new LinearLayout(getContext()); topbar.addView(ll,new LinearLayout.LayoutParams(0, LayoutParams.MATCH_PARENT,4)); buttonPast.setScaleType(ImageView.ScaleType.CENTER_INSIDE); topbar.addView(buttonPast, new LinearLayout.LayoutParams(0, LayoutParams.MATCH_PARENT,1)); title.setGravity(Gravity.CENTER); topbar.addView(title, new LinearLayout.LayoutParams( 0, LayoutParams.MATCH_PARENT, DEFAULT_DAYS_IN_WEEK - 2 )); buttonFuture.setScaleType(ImageView.ScaleType.CENTER_INSIDE); topbar.addView(buttonFuture, new LinearLayout.LayoutParams(0, LayoutParams.MATCH_PARENT,1)); pager.setId(R.id.mcv_pager); pager.setOffscreenPageLimit(1); addView(pager, new LayoutParams(calendarMode.visibleWeeksCount + DAY_NAMES_ROW)); }
很简单的线性布局,添加子view,修改左右切换的图标代码也在这个类里设置,代码如下:
修改以后发现图片是黑色的有木有,没有按照你的图片显示,呵呵,还有个地方需要注释一下:
就是他,注释掉就可以显示出你设置的图片了,一些topbar的修改,相信到这应该是可以适应大多数UI妹子的要求了。
继续往下走,接下来就是对周一,周二,周三,周四,周五,周六,周日的修改,首先是文字的修改:
属性mcv_weekDayLabels可以改变星期的的显示样式:分析源码可知他的值是一个array数组
CharSequence[] array = a.getTextArray(R.styleable.MaterialCalendarView_mcv_weekDayLabels); if (array != null) { setWeekDayFormatter(new ArrayWeekDayFormatter(array)); }可以在values文件夹下面新建一个xml文件如下:(xml文件名可以随便定义)
xml version="1.0" encoding="utf-8"?>为什么周日放第一个,原因如下:因为不想源码改动太多,就按这个标准来就OK啦name="week_title"> - 星期日
- 星期一
- 星期二
- 星期三
- 星期四
- 星期五
- 星期六
name="mcv_firstDayOfWeek" format="enum">
name="sunday" value="1" />
name="monday" value="2" />
name="tuesday" value="3" />
name="wednesday" value="4" />
name="thursday" value="5" />
name="friday" value="6" />
name="saturday" value="7" />
这是文字的修改,不过有些需求需要周六,周日用不同颜色标记,也不难,看weekDayView中的代码就可以随意改变控件的状态,包括背景色,关键代码如下:
public void setDayOfWeek(int dayOfWeek) { this.dayOfWeek = dayOfWeek; if(dayOfWeek==7||dayOfWeek==1){ setText(Html.fromHtml("\"#ff0000\">"+formatter.format(dayOfWeek)+"")); }else { setText(formatter.format(dayOfWeek)); } }为什么是dayOfWeek==7和1呢?原因同上。接下来该操作日期了,选中颜色的改变功能,那个修改网上案例比较多,这里不再赘述。
下面我分享一下添加标记的实现:
源码里面有个spans文件夹,下面有个DotSpan类,用他可以直接在日期下面加小红点的标记,具体使用如下
新建一个EventDecorator类实现DayViewDecorator方法,代码如下可以直接复制:
import com.prolificinteractive.materialcalendarview.CalendarDay; import com.prolificinteractive.materialcalendarview.DayViewDecorator; import com.prolificinteractive.materialcalendarview.DayViewFacade; import java.util.Collection; import java.util.HashSet; /** * Created by bobo on 2017/8/3. */ public class EventDecorator implements DayViewDecorator { private final int color; private final HashSet然后在你的日历操作文件中添加代码如下:dates; public EventDecorator(int color, Collection dates) { this.color = color; this.dates = new HashSet<>(dates); } @Override public boolean shouldDecorate(CalendarDay day) { return dates.contains(day); } @Override public void decorate(DayViewFacade view) { view.addSpan(new DotSpan(5, color)); } }
Collection如果觉得小红点距离上门的日期太近的话可以在DotSpan作如下修改dates=new ArrayList<>(); dates.add(new CalendarDay(new Date(str2long("2017-8-4","yyyy-MM-dd")))); dates.add(new CalendarDay(new Date(str2long("2017-8-5","yyyy-MM-dd")))); dates.add(new CalendarDay(new Date(str2long("2017-8-7","yyyy-MM-dd")))); dates.add(new CalendarDay(new Date(str2long("2017-8-8","yyyy-MM-dd")))); dates.add(new CalendarDay(new Date(str2long("2017-8-20","yyyy-MM-dd")))); materialCalendarView.addDecorator(new EventDecorator(Color.RED,dates));
@Override public void drawBackground( Canvas canvas, Paint paint, int left, int right, int top, int baseline, int bottom, CharSequence charSequence, int start, int end, int lineNum ) { int oldColor = paint.getColor(); if (color != 0) { paint.setColor(color); } canvas.drawCircle((left + right) / 2, bottom + radius+15, radius, paint); paint.setColor(oldColor); }至此小红点的标记就算结束了,不过有些需求需要在特定的日期里面加文字描述,这个我是参照这篇博客里面的方法实现的http://blog.csdn.net/gaoanchen/article/details/51147644大神对这个描述的也比较详细,如果有不懂的大家也可以和我一起学习,一起研究大神们的源码哦!
参考博客:http://blog.csdn.net/gaoanchen/article/details/51147644