MaterialCalendarView日历控件的使用小结

时间:2024-03-13 11:11:38

最近公司项目需要用到日历来实现某些功能,作为小菜的我首先就想到了去找现有的日历控件,不过朋友推荐说MaterialCalendarView非常非常的强大,于是我又开始了新一轮的“装逼”之路MaterialCalendarView日历控件的使用小结

GitHub链接奉上:https://github.com/prolificinteractive/material-calendarview

强力推荐大家按照GitHub上的文档开发,这里作为小菜的我,喜欢在别人的代码里找找“灵感”,于是乎就直接把他的关键类导入到了自己的项目(顺便说一下,按Module导入问题太多,懒的修改才直接考的源码MaterialCalendarView日历控件的使用小结,有木有很聪明MaterialCalendarView日历控件的使用小结)。先上效果图:MaterialCalendarView日历控件的使用小结

我导入的关键代码是library文件下的main代码和res下的相关代码,非常简单粗暴的操作

MaterialCalendarView日历控件的使用小结

接着就是点进去源码的世界里遨游,寻找“灵感”,分析效果图可以大致分为,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,修改左右切换的图标代码也在这个类里设置,代码如下:

MaterialCalendarView日历控件的使用小结

修改以后发现图片是黑色的有木有,没有按照你的图片显示,呵呵,还有个地方需要注释一下:MaterialCalendarView日历控件的使用小结

就是他,注释掉就可以显示出你设置的图片了,一些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"?>
<resources>
    <string-array name="week_title">
        <item> 星期日</item>
        <item >星期一</item>
        <item >星期二</item>
        <item >星期三</item>   
        <item> 星期四</item>
        <item> 星期五</item>
        <item> 星期六</item>
    </string-array>
</resources>
为什么周日放第一个,原因如下:因为不想源码改动太多,就按这个标准来就OK啦MaterialCalendarView日历控件的使用小结

<attr name="mcv_firstDayOfWeek" format="enum">
    <enum name="sunday" value="1" />
    <enum name="monday" value="2" />
    <enum name="tuesday" value="3" />
    <enum name="wednesday" value="4" />
    <enum name="thursday" value="5" />
    <enum name="friday" value="6" />
    <enum name="saturday" value="7" />
</attr>
这是文字的修改,不过有些需求需要周六,周日用不同颜色标记,也不难,看weekDayView中的代码就可以随意改变控件的状态,包括背景色,关键代码如下:

public void setDayOfWeek(int dayOfWeek) {
    this.dayOfWeek = dayOfWeek;
    if(dayOfWeek==7||dayOfWeek==1){
        setText(Html.fromHtml("<font color=\"#ff0000\">"+formatter.format(dayOfWeek)+"</font>"));
    }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<CalendarDay> dates;

    public EventDecorator(int color, Collection<CalendarDay> 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<CalendarDay> 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));
如果觉得小红点距离上门的日期太近的话可以在DotSpan作如下修改

@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