目前项目中实现的效果是默认是当天,然后效果是实心的矩形框。如果选中别的日期今天的日期变成空心矩形框,选中的日期显示是实心的矩形框。然后根据当天有没有训练数据展示实心的圆点效果。很类似OPPO手机原带的日历效果。当前是根据NCalendar自定义效果实现。
整体的效果是自定义CalendarPainter实现,代码中根据是不是今天绘制效果 以及是否被选中 画笔绘制矩形框。以及单独的绘制今天是否有任务的红点。方法中都有注释。
public class CustomPainter implements CalendarPainter { protected Paint mTextPaint; protected Paint mBgPaint; //圆点的半径 private int mCircleRadius; private Context mContext; private ICalendar mICalendar; protected Paint mSelectenPaint; private List<LocalDate> mPointList; public CustomPainter(Context context, ICalendar iCalendar) { mContext = context; mICalendar = iCalendar; mTextPaint = getPaint(); mBgPaint = getmBgPaint(); mSelectenPaint = getmSelectenPaint(); mPointList = new ArrayList<>(); mCircleRadius = DensityUtil.dp2px(2); } private Paint getPaint() { Paint paint = new Paint(); paint.setAntiAlias(true); paint.setTextAlign(Paint.Align.CENTER); return paint; } private Paint getmSelectenPaint() { mSelectenPaint = new Paint(); mSelectenPaint.setAntiAlias(true); mSelectenPaint.setStyle(Paint.Style.FILL); mSelectenPaint.setColor(0xFFFF2271); return mSelectenPaint; } /** * 当前背景 * * @return */ private Paint getmBgPaint() { Paint mCurrentDayPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mCurrentDayPaint.setAntiAlias(true); mCurrentDayPaint.setStrokeWidth(DensityUtil.dp2px(1)); mCurrentDayPaint.setStyle(Paint.Style.STROKE); mCurrentDayPaint.setColor(0xFFFF2271); return mCurrentDayPaint; } @Override public void onDrawToday(Canvas canvas, RectF rectF, LocalDate localDate, List<LocalDate> checkedDateList) { //如果是今天的话 绘制矩形 drawSelectBg(canvas, rectF, CalendarUtil.isToday(localDate), checkedDateList.contains(localDate)); drawSolar(canvas, rectF, localDate, checkedDateList.contains(localDate), true); drawPoint(canvas, rectF, localDate); } @Override public void onDrawCurrentMonthOrWeek(Canvas canvas, RectF rectF, LocalDate localDate, List<LocalDate> checkedDateList) { drawSelectBg(canvas, rectF, CalendarUtil.isToday(localDate), checkedDateList.contains(localDate)); drawSolar(canvas, rectF, localDate, checkedDateList.contains(localDate), true); drawPoint(canvas, rectF, localDate); } @Override public void onDrawLastOrNextMonth(Canvas canvas, RectF rectF, LocalDate localDate, List<LocalDate> checkedDateList) { drawSelectBg(canvas, rectF, CalendarUtil.isToday(localDate), checkedDateList.contains(localDate)); drawSolar(canvas, rectF, localDate, checkedDateList.contains(localDate), true); drawPoint(canvas, rectF, localDate); } //绘制公历 private void drawSolar(Canvas canvas, RectF rectF, LocalDate localDate, boolean isSelected, boolean isCurrectMonthOrWeek) { mTextPaint.setTextSize(DensityUtil.dp2px(16)); //如果是今天 并且被选中 if (CalendarUtil.isToday(localDate) && isSelected) { mTextPaint.setColor(Color.WHITE); //如果是今天没被选中 } else if (CalendarUtil.isToday(localDate)) { mTextPaint.setColor(Color.RED); } else { //其他情况就是被选中的就是白色 不被选中就是黑色 mTextPaint.setColor(isSelected ? Color.WHITE : Color.BLACK); } mTextPaint.setAlpha(isCurrectMonthOrWeek ? 255 : 100); canvas.drawText(localDate.getDayOfMonth() + "", rectF.centerX(), getBaseLineY(rectF), mTextPaint); } //canvas.drawText的基准线 private int getBaseLineY(RectF rectF) { Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics(); float top = fontMetrics.top; float bottom = fontMetrics.bottom; int baseLineY = (int) (rectF.centerY() - top / 2 - bottom / 2); return baseLineY; } //绘制选中背景 private void drawSelectBg(Canvas canvas, RectF rectF, boolean isToday, boolean isisSelected) { float v = rectF.centerX(); float y = rectF.centerY(); float left = rectF.left; float right = rectF.right; float top = rectF.top; float bottom = rectF.bottom; L.e("当前的上下左右", "中x" + v + "中y" + y + "左" + left + "右" + right + "上" + top + "下" + bottom); //float left, float top, float right, float bottom rectF.set(v - DensityUtil.dp2px(15), y - DensityUtil.dp2px(15), v + DensityUtil.dp2px(15), y + DensityUtil.dp2px(15)); if (isToday && isisSelected) { canvas.drawRoundRect(rectF, 8f, 8f, mSelectenPaint); } else if (isToday) { // 画圆角矩形 canvas.drawRoundRect(rectF, 8f, 8f, mBgPaint); } else if (isisSelected) { canvas.drawRoundRect(rectF, 8f, 8f, mSelectenPaint); } } /** * dp转px * * @param context context * @param dpValue dp * @return px */ public int dipToPx(Context context, float dpValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (dpValue * scale + 0.5f); } /** * 画圆点 */ //设置标记 public void setPointList(List<String> list) { mPointList.clear(); for (int i = 0; i < list.size(); i++) { LocalDate localDate = null; try { localDate = new LocalDate(list.get(i)); } catch (Exception e) { throw new RuntimeException("setPointList的参数需要 yyyy-MM-dd 格式的日期"); } mPointList.add(localDate); } mICalendar.notifyCalendar(); } //绘制哪一天有课程 private void drawPoint(Canvas canvas, RectF rectF, LocalDate localDate) { if (mPointList.contains(localDate)) { canvas.drawCircle(rectF.centerX(), rectF.centerY() + DensityUtil.dp2px(20), mCircleRadius, mSelectenPaint); } } }
翻页的时候获取每个月中有当前是否有任务数据然后设置给Calendar 重新绘制圆点setPointList()f方法
/*** * 获取本月数据 */ private void getPlanOfMonth(String selectMonth) { new MineMissionPresenter().getCalendarHistory(selectMonth, new HttpJsonCallback<JSONArray>() { @Override public void requestSuccess(JSONArray jsonArray) { ArrayList<TrainHistoryMonthBean> list = GsonUtil.fromListJson(jsonArray.toString(), TrainHistoryMonthBean.class); if (list != null && list.size() != 0) { for (TrainHistoryMonthBean bean : list) { if (bean.getHasPlan() > 0 || bean.getHasCourse() > 0 || bean.getHasPlanMission() > 0) { String ymd = bean.getYmd(); if (!mList.contains(ymd)) { mList.add(ymd); } } } if (painter != null) { painter.setPointList(mList); } } } @Override public void onError(String error) { } }); }