日历控件有很多,但是如果要实现在日历上标注文字或者图片,该如何实现呢,小菜鸟一枚,下面写写我在项目里用到的一个控件--MaterialCalendarView, 基于MaterailDesign风格De日历,据说最早是由外国人写的,然后开源出来了,之所以会选中这个是他可以较方便的在日历上添加标记,而且MaterailDesign风格的很受大家好评,做项目的时候网上找了好些资料,也找了发过类似帖子的大神支援。好了下面是我的项目的demo跟效果图
这个是我项目中一个模块的截图,下面那部分日历就是效果图啦。
1.布局文件
仅提供那两个array/custom_myweekdays 和 array/custom_mymonths写在Strings.xml里,剩下的在类库里都有了
- 日
- 一
- 二
- 三
- 四
- 五
- 六
- 一月
- 二月
- 三月
- 四月
- 五月
- 六月
- 七月
- 八月
- 九月
- 十月
- 十一月
- 十二月
2.接下来是Activity
private MaterialCalendarView calendarView;
private Calendar calendar;
private OneDayDecorator oneDayDecorator= new OneDayDecorator();
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.orders_everyday_frag, container, false);
calendarView= (MaterialCalendarView) view.findViewById(R.id.calendarView);
calendarView.setOnDateChangedListener(this);
calendarView.setOnMonthChangedListener(this);
calendar = Calendar.getInstance();
calendarView.setFirstDayOfWeek(calendar.SUNDAY);//设置一周起始日
calendarView.setSelectedDate(calendar.getTime());//当日选中
//系统当前日期的颜色
calendarView.addDecorators(new MyBackgroundDecorator(getActivity(), R.drawable.my_selector_orange,
CalendarDay.from(calendar.getTime())));
//选中日期的颜色
calendarView.addDecorators(new MySelectorDecorator(getActivity(), R.drawable.my_selector_blue),
oneDayDecorator);
//在日期上添加标记或者图片,需要用到实体类-->EventDecorator.class
list.add(new EventDecorator(getContext(),new int[]{1,orderSchedule.getServiceOrderCount() ,orderSchedule.getNewOrderCount()},strTranCalendar(orderSchedule.getWorkDate())));
//setData(systemTime);更新ui
return view;
}
public CalendarDay strTranCalendar(String str){
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
try {
Date date = dateFormat.parse(str);
calendar.setTime(date);
CalendarDay calendarDay = CalendarDay.from(calendar);
return calendarDay;
} catch (ParseException e) {
e.printStackTrace();return null;
}
}
//这个方法是,选中某个日期以后执行的方法,注意date的格式需要根据自己的需要处理一下
@Override
public void onDateSelected(@NonNull MaterialCalendarView widget, @NonNull CalendarDay date, boolean selected) {
if (selected){
String substring = date.toString().substring(0, date.toString().length() - 1);
String[] split = substring.split("[{]");//特殊字符,需要转义2015-0-8
//....此处省略部分代码
}
}
//这个方法是,当左右滑动切换月份时,执行的方法
@Override
public void onMonthChanged(MaterialCalendarView widget, CalendarDay date) {
String s = DateFormatUtils.getFormatDate(date, true);//滑动后显示的月份
String curMonth = systemTime.substring(0, 7);//当前月:2015-02
}
除此之外,你还需要这几个类
其中MypointSpan是绘图的核心代码,其他几个类是类库里本身就有的,如果有需要可以在自定义一下,下面讲一下MyPointSpan.class:
public class MyPointSpan implements LineBackgroundSpan {
private Context context;
public static final float DEFAULT_RADIUS = 3;
private final float radius;
//预先定义好的颜色
private final int[] color=new int[]{1,2,3,4};
//接收过来的数据
private final int[] data;
public MyPointSpan() {
this.radius = DEFAULT_RADIUS;
this.data = null;
}
public MyPointSpan(int[] color) {
this.radius = DEFAULT_RADIUS;
this.data = color;
}
public MyPointSpan(float radius) {
this.radius = radius;
this.data = null;
}
public MyPointSpan(Context context,float radius, int[] data) {
this.context=context;
this.radius = radius;
this.data = data;
}
@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
) {
Resources res = context.getResources();
float common_font_sw320dp_of_10 = res.getDimension(R.dimen.common_font_sw320dp_of_10);//引用dimen文件,方便屏幕适配
int oldColor = paint.getColor();
//新加
float oldTextSize = paint.getTextSize();
paint.setTextAlign(Paint.Align.LEFT);
if(data.length!= 0&&!data.equals(null)) {
String text1;
String text2;
//清除画布
/*paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
canvas.drawPaint(paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));*/
switch (data[0]){
case 1:
//当前日期及其当前日期之后的---区分显示--1
//服务中订单
paint.setColor(getColor(color[0]));
paint.setTextSize(common_font_sw320dp_of_10);
canvas.drawText(data[2] + "/", (left + right) / 4 - radius, bottom + top + radius + 12, paint);
//新增订单
paint.setColor(getColor(color[2]));
paint.setTextSize(common_font_sw320dp_of_10);
canvas.drawText(data[1]+"", (left + right) / 2+ radius, bottom+top + radius+12, paint);
paint.setTextSize(oldTextSize);
paint.setColor(oldColor);
paint.setTextAlign(Paint.Align.LEFT);
break;
}
}
paint.setColor(oldColor);
}
public int getColor(int colorNum){
int circleColor=0;
switch (colorNum){
case 1:
int i = Color.parseColor("#fc7c0f");
circleColor=i;break; //闲
case 2:circleColor= Color.GRAY;break; //过去的日期显示灰色
case 3:
int j=Color.parseColor("#1eb9cf");
circleColor=j;break; //忙
case 4:circleColor=Color.BLACK;
break; //分割线
}
return circleColor;
}
}
}
当需要在画布上重新绘制标记的时候,想到的有两种方式:一是清除画布,但是有个很致命的缺陷就是,画布的背景色会变成黑色,试了好多种方法都没有效果
清除画布的代码:
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
canvas.drawPaint(paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
第二种方式是:设置画笔的背景色background是白色,实验证明,确实有效果,但是别忘了,日历上当前日期是有圆形的背景图的,这个background会覆盖掉他。。。
最好不得已,只能让他的生命周期重新走一遍,然后重新绘制,在这里征求大家的心得,有没有更好的方式!
小菜鸟一枚,具体的代码剖析还请看-->http://blog.csdn.net/miss_qz14/article/details/50014617 感谢大神的帮助~