项目中最近有用到记录女性经期的功能,类似于美柚经期日历效果,然后找遍了都没找到,无奈只能自己写了。
为了节约时间和成本,直接是基于三方开源日历库修改的。
三方开源库: CalendarView 超级好用,自定义程度高,强烈推荐~~
可参考文档:CalendarView文档
效果图
前言:
看了文档和介绍你就知道,你只要关心如何将你要的效果(例如颜色、标记等)显示在日历上面就行了,其他的已经帮你处理好了,你只需要通过Canvas绘制出来就行了,坐标也都计算好了。
分析:
新建类继承MonthView(月视图),分别实现:
onDrawSelected(Canvas canvas, Calendar calendar, int x, int y, boolean hasScheme)
onDrawScheme(Canvas canvas, Calendar calendar, int x, int y)
onDrawText(Canvas canvas, Calendar calendar, int x, int y, boolean hasScheme,boolean isSelected)
三个方法对应的是:选中效果、标记效果、文本效果
可以看出他已经返回了坐标和Canvas对象,所以我们只要根据需要绘制就行了。例如我们要日期被选中时设置它的背景颜色,那么我们只要在onDrawSelected()方法中去绘制,下面是代码示例(这里是绘制了一个矩形):
/**
* @param mSelectedPaint 被选择的日期背景色画笔
* @param mPadding 设置间距
* @param mItemWidth 每一项的宽度
* 绘制选中效果示例
*/
@Override
protected boolean onDrawSelected(Canvas canvas, Calendar calendar, int x, int y, boolean hasScheme) {
canvas.drawRect(x + mPadding, y + mPadding, x + mItemWidth - mPadding, y + mItemHeight - mPadding, mSelectedPaint);
return true;
}
其他的也是同理,根据需要进行绘制。
对于经期日历来说,它分为安全期、排卵期、易孕期、月经期等等,我们就需要针对不同月经日期绘制不同的背景颜色,用于区分,如安全期时,颜色为绿色,月经期时就为粉色.....
所以我们就只要知道它哪一天为安全期、哪一天为易孕期,然后绘制不同的颜色就行了。
这里的话我给出两种方式,可以自行权量:
1、直接依赖他的库,不作任何修改,然后依据他的标记字段 scheme 作为日期类别区分
他有一个方法calendar.setScheme(String scheme),就是用来设置标记字段的,你可以将这个字段用来显示在日历上,如果你不需要在日历上显示额外的标记信息,那你就可以将此字段作为日期类别来用。(本文的示例代码就是通过此方式来使用的)
//部分代码示例(根据Scheme字段来判断,period为月经期 ovulation排卵日)
@Override
protected void onDrawScheme(Canvas canvas, Calendar calendar, int x, int y) {
if ("period".equals(calendar.getScheme())) {//月经期绘制粉色背景
canvas.drawRect(x + mPadding, y + mPadding, x + mItemWidth - mPadding, y + mItemHeight - mPadding, mSchemePaint);
return;//减少判断
}
if ("ovulation".equals(calendar.getScheme())) {//排卵期有特别标示(底部小横线)
mPointPaint.setColor(0xFFE4CFFB);
canvas.drawRect(x + mItemWidth / 2 - mW / 2,
y + mItemHeight - mH * 2 - mPadding,
x + mItemWidth / 2 + mW / 2,
y + mItemHeight - mH - mPadding, mPointPaint);
}
}
2、导入他的库,进行修改
我们可以仿照他的标记scheme字段,添加一个自己的标记字段,如下图:
public String getScheme() {
return scheme;
}
//设置标记(他的方法)
public void setScheme(String scheme) {
this.scheme = scheme;
}
public int getSchemeType() {
return schemeType;
}
//设置类别(自己添加的方法)
public void setSchemeType(int schemeType) {
this.schemeType = schemeType;
}
然后依次修改下面三个类中的三个方法:
Calendar类: mergeScheme(Calendar calendar, String defaultScheme)
final void mergeScheme(Calendar calendar, String defaultScheme) {
if (calendar == null)
return;
setScheme(TextUtils.isEmpty(calendar.getScheme()) ?
defaultScheme : calendar.getScheme());
setSchemeColor(calendar.getSchemeColor());
setSchemeType(calendar.getSchemeType());//设置类别(自己添加的)
setSchemes(calendar.getSchemes());
}
CalendarViewDelegate类: addSchemesFromMap(List<Calendar> mItems)
final void addSchemesFromMap(List<Calendar> mItems) {
if (mSchemeDatesMap == null || mSchemeDatesMap.size() == 0) {
return;
}
for (Calendar a : mItems) {
if (mSchemeDatesMap.containsKey(a.toString())) {
Calendar d = mSchemeDatesMap.get(a.toString());
a.setScheme(TextUtils.isEmpty(d.getScheme()) ? getSchemeText() : d.getScheme());
a.setSchemeColor(d.getSchemeColor());
a.setSchemeType(d.getSchemeType());//设置类别(自己添加的)
a.setSchemes(d.getSchemes());
} else {
a.setScheme("");
a.setSchemeColor(0);
a.setSchemeType(0);//设置类别(自己添加的)
a.setSchemes(null);
}
}
}
BaseView类: addSchemesFromMap()
final void addSchemesFromMap() {
if (mDelegate.mSchemeDatesMap == null || mDelegate.mSchemeDatesMap.size() == 0) {
return;
}
for (Calendar a : mItems) {
if (mDelegate.mSchemeDatesMap.containsKey(a.toString())) {
Calendar d = mDelegate.mSchemeDatesMap.get(a.toString());
a.setScheme(TextUtils.isEmpty(d.getScheme()) ? mDelegate.getSchemeText() : d.getScheme());
a.setSchemeColor(d.getSchemeColor());
a.setSchemeType(d.getSchemeType());//设置类别(自己添加的)
a.setSchemes(d.getSchemes());
} else {
a.setScheme("");
a.setSchemeColor(0);
a.setSchemeType(0);//设置类别(自己添加的)
a.setSchemes(null);
}
}
}
修改完成后,我们只需在设置数据的时候将类别填写进去,然后绘制的时候根据我们设置的SchemeType字段去分区日期,然后对应绘制就行了。
更多细节可参考示例Demo或者CalendarView文档
Github直达链接
欢迎Start或提issues!