记一次Android第三方日历控件CalendarView的使用

一、文章背景

用过两个日历控件的库,有用viewpager实现的,也有用canvas实现的。在实际使用过程中,发现使用canvas实现的calendarView切换下一月和下一年这种操作时切换更流畅。

我这里主要记录上一年和下一年的使用,其他功能大家可以参考第三方库的使用Github

二、日历控件的使用

2.1、实现MonthView

package com.wyy.usecalendarview

import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.RectF
import androidx.core.content.ContextCompat
import com.haibin.calendarview.Calendar
import com.haibin.calendarview.MonthView

class ScheduleMonthView(context: Context) : MonthView(context) {
    /**
     * 背景圆点
     */
    private val mPointPaint = Paint()

    /**
     * 今天的背景色
     */
    private val mCurrentDayPaint = Paint()

    /**
     * 圆点半径
     */
    private var mPointRadius = 3f

    init {
        mCurrentDayPaint.isAntiAlias = true
        mCurrentDayPaint.style = Paint.Style.FILL
        mCurrentDayPaint.color = ContextCompat.getColor(context, R.color.purple_700)
        mPointPaint.isAntiAlias = true
        mPointPaint.style = Paint.Style.FILL
        mPointPaint.textAlign = Paint.Align.CENTER
        mPointPaint.color = ContextCompat.getColor(context, R.color.purple_200)
    }

    /**
     * 绘制选中的日子(这个绘制会覆盖标记点的显示)
     *
     * @param canvas    canvas
     * @param calendar  日历日历calendar
     * @param x         日历Card x起点坐标
     * @param y         日历Card y起点坐标
     * @param hasScheme hasScheme 非标记的日期
     * @return 返回true 则绘制onDrawScheme,因为这里背景色不是是互斥的,所以返回true
     */
    override fun onDrawSelected(canvas: Canvas, calendar: Calendar, x: Int, y: Int, hasScheme: Boolean): Boolean {
        if (!calendar.isCurrentDay) {
            mSelectedPaint.style = Paint.Style.STROKE
            mSelectedPaint.strokeWidth = 2f
            val rectF = RectF(x.toFloat(), y.toFloat(), (x + mItemWidth).toFloat(), (y + mItemHeight).toFloat())
            canvas.drawRoundRect(rectF, 16f, 16f, mSelectedPaint)
        }
        return true
    }

    /**
     * 绘制标记的事件日子(只绘制非当天的标记点,避免重复绘制)
     *
     * @param canvas   canvas
     * @param calendar 日历calendar
     * @param x        日历Card x起点坐标
     * @param y        日历Card y起点坐标
     */
    override fun onDrawScheme(canvas: Canvas, calendar: Calendar, x: Int, y: Int) {
        if (!calendar.isCurrentDay) {
            canvas.drawCircle((x + mItemWidth / 2).toFloat(), (y + mItemHeight - 13).toFloat(), mPointRadius, mPointPaint)
        }
    }

    /**
     * 绘制文本(如果今天有标记点,这里还需要绘制当天的标记点)
     *
     * @param canvas     canvas
     * @param calendar   日历calendar
     * @param x          日历Card x起点坐标
     * @param y          日历Card y起点坐标
     * @param hasScheme  是否是标记的日期
     * @param isSelected 是否选中
     */
    override fun onDrawText(canvas: Canvas?, calendar: Calendar?, x: Int, y: Int, hasScheme: Boolean, isSelected: Boolean) {
        val cx = x + mItemWidth / 2
        calendar?.let {
            canvas?.let { cit ->
                if (it.isCurrentDay) {
                    val rectF = RectF(x.toFloat(), y.toFloat(), (x + mItemWidth).toFloat(), (y + mItemHeight).toFloat())
                    cit.drawRoundRect(rectF, 16f, 16f, mCurrentDayPaint)
                    if (hasScheme) {
                        //  绘制当天的标记点
                        cit.drawCircle(
                            (x + mItemWidth / 2).toFloat(),
                            (y + mItemHeight - 13).toFloat(),
                            mPointRadius,
                            mPointPaint
                        )
                    }
                }
                val drawPaint = if (isSelected && !it.isCurrentDay) {
                    mSelectTextPaint
                } else if (hasScheme) {
                    if (it.isCurrentMonth) mSchemeTextPaint else mOtherMonthTextPaint
                } else {
                    if (it.isCurrentDay) mCurDayTextPaint else if (it.isCurrentMonth) mCurMonthTextPaint else mOtherMonthTextPaint
                }
                cit.drawText(it.day.toString(), cx.toFloat(), mTextBaseLine + y, drawPaint)
            }
        }
    }
}

2.2、布局代码使用示例:

2.3、注册日历的事件监听

2.3.1、监听月份切换

mDataBinding.cvCalendar.setOnMonthChangeListener(this)

2.3.2、监听选择事件

mDataBinding.cvCalendar.setOnCalendarSelectListener(this)

2.4、实现日历的监听事件

2.4.1、月份切换的实现

    override fun onMonthChange(year: Int, month: Int) {
        supportActionBar?.title = getString(R.string.title, year, month)
    }

2.4.2、选择事件的实现

    /**
     * 没用到
     */
    override fun onCalendarOutOfRange(calendar: Calendar?) {}

    /**
     * 用户选择的监听
     */
    override fun onCalendarSelect(calendar: Calendar?, isClick: Boolean) {
        Log.d(
            "wyy",
            "Selector year is ${calendar?.year},month is ${calendar?.month},day is ${calendar?.day} and isClick is $isClick"
        )
    }

2.5、操作日历控件

2.5.1、上一年

            mDataBinding.cvCalendar.monthViewPager.apply {
                currentItem -= 12
            }

2.5.2、下一年

            mDataBinding.cvCalendar.monthViewPager.apply {
                currentItem += 12
            }

2.6、demo

Github

你可能感兴趣的:(Android,CalendarView,日历控件,android,日历控件)