转发链接:https://blog.csdn.net/huanghaibin_dev/article/details/79040147
github中文文档:https://github.com/huanghaibin-dev/CalendarView/blob/master/QUESTION_ZH.md
github地址:https://github.com/huanghaibin-dev/CalendarView
由于该插件比较灵活,可以自定义View来实现日历功能,毫不犹豫地就采用该插件来实现项目的日历功能,项目需要实现的效果:
接入插件步骤:
一、在app的build.gradle中添加依赖:
implementation 'com.haibin:calendarview:3.6.6'
二、布局文件
<com.haibin.calendarview.CalendarLayout android:id="@+id/calendarLayout" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#fff" android:orientation="vertical" app:calendar_content_view_id="@+id/recyclerView" app:calendar_show_mode="only_month_view"> <com.haibin.calendarview.CalendarView android:id="@+id/calendarView" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#fff" android:clickable="false" app:calendar_padding="10dp" app:current_month_lunar_text_color="@color/fontColor_05" app:current_month_text_color="#333333" app:month_view="com.utils.colorful.ColorfulMonthView" app:month_view_show_mode="mode_fix" app:other_month_lunar_text_color="@color/White" app:other_month_text_color="@color/fontColor_05" app:scheme_text_color="#fff" app:scheme_theme_color="@color/colorPrimary" app:selected_lunar_text_color="@color/White" app:selected_text_color="@color/White" app:week_start_with="mon" app:week_text_color="@color/fontColor_05" app:week_text_size="16sp" app:week_view="com.utils.meizu.MeizuWeekView" app:year_view_day_text_color="@color/fontColor_07" app:year_view_day_text_size="7sp" app:year_view_month_text_color="#ff0000" app:year_view_month_text_size="20sp" app:year_view_scheme_color="#f17706" app:year_view_select_text_color="#fff" app:year_view_week_height="12dp" app:year_view_week_text_color="@color/fontColor_05" app:year_view_week_text_size="6sp" /> </com.haibin.calendarview.CalendarLayout>
加入该段代码便可以实现一般的日历功能,需要定制日历样式的话就继承周、月、年视图来自定义视图样式。
三、继承MonthView、WeekView、YearView类
由于只需要展示该月份的日历视图,故只继承了MonthView类(参考了demo的ColorfulWeekView类)
public class ColorfulWeekView extends WeekView { private int mRadius; public ColorfulWeekView(Context context) { super(context); //兼容硬件加速无效的代码 setLayerType(View.LAYER_TYPE_SOFTWARE, mSelectedPaint); //4.0以上硬件加速会导致无效 mSelectedPaint.setMaskFilter(new BlurMaskFilter(30, BlurMaskFilter.Blur.SOLID)); setLayerType(View.LAYER_TYPE_SOFTWARE, mSchemePaint); mSchemePaint.setMaskFilter(new BlurMaskFilter(30, BlurMaskFilter.Blur.SOLID)); } @Override protected void onPreviewHook() { mRadius = Math.min(mItemWidth, mItemHeight) / 5 * 2; } /** * 如果需要点击Scheme没有效果,则return true * * @param canvas canvas * @param calendar 日历日历calendar * @param x 日历Card x起点坐标 * @param hasScheme hasScheme 非标记的日期 * @return false 则不绘制onDrawScheme,因为这里背景色是互斥的 */ @Override protected boolean onDrawSelected(Canvas canvas, Calendar calendar, int x, boolean hasScheme) { int cx = x + mItemWidth / 2; int cy = mItemHeight / 2; canvas.drawCircle(cx, cy, mRadius, mSelectedPaint); return true; } @Override protected void onDrawScheme(Canvas canvas, Calendar calendar, int x) { int cx = x + mItemWidth / 2; int cy = mItemHeight / 2; canvas.drawCircle(cx, cy, mRadius, mSchemePaint); } @SuppressWarnings("IntegerDivisionInFloatingPointContext") @Override protected void onDrawText(Canvas canvas, Calendar calendar, int x, boolean hasScheme, boolean isSelected) { int cx = x + mItemWidth / 2; int top = -mItemHeight / 8; if (isSelected) { canvas.drawText(String.valueOf(calendar.getDay()), cx, mTextBaseLine + top, calendar.isCurrentDay() ? mCurDayTextPaint : mSelectTextPaint); canvas.drawText(calendar.getLunar(), cx, mTextBaseLine + mItemHeight / 10, calendar.isCurrentDay() ? mCurDayLunarTextPaint : mSelectedLunarTextPaint); } else if (hasScheme) { canvas.drawText(String.valueOf(calendar.getDay()), cx, mTextBaseLine + top, calendar.isCurrentDay() ? mCurDayTextPaint : calendar.isCurrentMonth() ? mSchemeTextPaint : mSchemeTextPaint); canvas.drawText(calendar.getLunar(), cx, mTextBaseLine + mItemHeight / 10, mSchemeLunarTextPaint); } else { canvas.drawText(String.valueOf(calendar.getDay()), cx, mTextBaseLine + top, calendar.isCurrentDay() ? mCurDayTextPaint : calendar.isCurrentMonth() ? mCurMonthTextPaint : mCurMonthTextPaint); canvas.drawText(calendar.getLunar(), cx, mTextBaseLine + mItemHeight / 10, calendar.isCurrentDay() ? mCurDayLunarTextPaint : mCurMonthLunarTextPaint); } } }
四、在Activty中添加展示数据
核心代码:
protected void initData() { int year = mCalendarView.getCurYear(); int month = mCalendarView.getCurMonth(); Map<String, Calendar> map = new HashMap<>(); for (int i = 1; i < 31; i++) { if (i <= 7) { map.put(getSchemeCalendar(year, month, i, getResources().getColor(R.color.colorPrimary), "假").toString(), getSchemeCalendar(year, month, i, getResources().getColor(R.color.colorPrimary), "假")); } else if (i <= 14) { map.put(getSchemeCalendar(year, month, i, getResources().getColor(R.color.Green), "假").toString(), getSchemeCalendar(year, month, i, getResources().getColor(R.color.Green), "假")); } else if (i <= 21) { map.put(getSchemeCalendar(year, month, i, getResources().getColor(R.color.YellowGreen), "假").toString(), getSchemeCalendar(year, month, i, getResources().getColor(R.color.YellowGreen), "假")); } else if (i <= 30) { map.put(getSchemeCalendar(year, month, i, getResources().getColor(R.color.Yellow), "假").toString(), getSchemeCalendar(year, month, i, getResources().getColor(R.color.Yellow), "假")); } } //此方法在巨大的数据量上不影响遍历性能,推荐使用 mCalendarView.setSchemeDate(map); mCalendarView.setMonthViewScrollable(false); mCalendarView.setWeekViewScrollable(false); //设置日期拦截事件 mCalendarView.setOnCalendarInterceptListener(new CalendarView.OnCalendarInterceptListener() { @Override public boolean onCalendarIntercept(Calendar calendar) { //这里写拦截条件,返回true代表拦截,尽量以最高效的代码执行 return true; } @Override public void onCalendarInterceptClick(Calendar calendar, boolean isClick) { //todo 点击拦截的日期回调 } }); mCalendarView.setClickable(false); mCalendarView.setEnabled(false); }
private Calendar getSchemeCalendar(int year, int month, int day, int color, String text) { Calendar calendar = new Calendar(); calendar.setYear(year); calendar.setMonth(month); calendar.setDay(day); calendar.setSchemeColor(color);//如果单独标记颜色、则会使用这个颜色 calendar.setScheme(text); calendar.addScheme(new Calendar.Scheme()); calendar.addScheme(0xFF008800, "假"); calendar.addScheme(0xFF008800, "节"); return calendar; }
五、运行效果