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

Android 专栏收录该内容
29 篇文章 1 订阅

一、文章背景

用过两个日历控件的库,有用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、布局代码使用示例:

<com.haibin.calendarview.CalendarView
            android:id="@+id/cv_calendar"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            app:calendar_height="40dp"
            app:current_day_text_color="@color/black"
            app:current_month_text_color="@color/black"
            app:day_text_size="14sp"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/toolbar"
            app:layout_constraintRight_toRightOf="parent"
            app:month_view="com.wyy.usecalendarview.ScheduleMonthView"
            app:other_month_text_color="@color/teal_700"
            app:selected_text_color="@color/black"
            app:selected_theme_color="@color/purple_700"
            app:week_background="@android:color/transparent"
            app:week_bar_height="40dp"
            app:week_text_color="@color/black"
            app:week_text_size="14sp"
            app:month_view_show_mode="mode_all"
            app:select_mode="single_mode" />

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

  • 0
    点赞
  • 0
    评论
  • 1
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

参与评论 您还未登录,请先 登录 后发表或查看评论
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页

打赏作者

yann02

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值