美文网首页
CalendarView使用笔记

CalendarView使用笔记

作者: 紫鹰 | 来源:发表于2022-03-11 10:21 被阅读0次

背景

遇到一个需求,自定义一个日历。日历有两种背景展示,文字有三种颜色

于是github上找了一个满足条件且star最多的自定义日历的控件

项目地址

https://github.com/huanghaibin-dev/CalendarView

优势

canves绘制,方便实现背景颜色样式、文字内容和颜色的自定义控制

使用

<com.haibin.calendarview.CalendarView android:id="@+id/calendarView" 
  android:layout_width="match_parent" android:layout_height="wrap_content" 
  android:layout_marginTop="@dimen/dp_32" android:background="#fff"     
  app:current_month_lunar_text_color="#CFCFCF" 
  app:current_month_text_color="#333333" app:layout_constraintLeft_toLeftOf="parent" 
  app:layout_constraintTop_toBottomOf="@+id/tv_current_month" app:min_year="2004" 
  app:month_view="XXX.SportsMatchMonthView" 
  app:month_view_show_mode="mode_only_current" 
  app:other_month_text_color="#e1e1e1" app:scheme_lunar_text_color="#ffffff" 
  app:scheme_text="假" app:scheme_text_color="#fff" 
  app:scheme_theme_color="#128c4b" app:selected_lunar_text_color="#fff" 
  app:selected_text_color="#fff" app:selected_theme_color="#108cd4" 
  app:week_background="#fff" app:week_text_color="#111" 
  app:year_view_day_text_color="#333333" app:year_view_day_text_size="9sp" 
  app:year_view_month_text_color="#ff0000" app:year_view_month_text_size="20sp" 
  app:year_view_scheme_color="#f17706" />

如下配置代码是自定义样式内容的入口

<com.haibin.calendarview.CalendarView android:id="@+id/calendarView" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:layout_marginTop="@dimen/dp_32"
    android:background="#fff" 
    app:current_month_lunar_text_color="#CFCFCF" 
    app:current_month_text_color="#333333" 
    app:layout_constraintLeft_toLeftOf="parent" 
    app:layout_constraintTop_toBottomOf="@+id/tv_current_month" 
    app:min_year="2004" app:month_view="XXX.SportsMatchMonthView" 
    app:month_view_show_mode="mode_only_current" 
    app:other_month_text_color="#e1e1e1" 
    app:scheme_lunar_text_color="#ffffff" 
    app:scheme_text="假" app:scheme_text_color="#fff" 
    app:scheme_theme_color="#128c4b" app:selected_lunar_text_color="#fff" 
    app:selected_text_color="#fff" app:selected_theme_color="#108cd4" 
    app:week_background="#fff" app:week_text_color="#111" 
    app:year_view_day_text_color="#333333" 
    app:year_view_day_text_size="9sp" 
    app:year_view_month_text_color="#ff0000" 
    app:year_view_month_text_size="20sp" 
    app:year_view_scheme_color="#f17706" />

该XXX.SportsMatchMonthView继承自MonthView,代码如下

public class SportsMatchMonthView extends MonthView {
    public SportsMatchMonthView(Context context) {
     super(context);
    } 
    @Override
     protected void onPreviewHook() { 
    }
    /**
    如果需要点击Scheme没有效果,则return true
     *
     * @param canvas canvas
     * @param calendar 日历日历calendar
     * @param x 日历Card x起点坐标
     * @param y 日历Card y起点坐标
     * @param hasScheme hasScheme 非标记的日期
     * @return false 则不绘制onDrawScheme,因为这里背景色是互斥的
     */
     @Override
     protected boolean onDrawSelected(Canvas canvas, Calendar calendar, int x, int y, boolean hasScheme) { 
        return true;
     } 
    /**
     * 左右相对日期控件本身缩进比例
     */
     private float widthGapRadio = 0.04f;
     /**
     * 上下相对日期控件本身缩进比例
     */
     private float heightGapRadio = 0.06f; 
    /**
     * 默认文字大小
     */
     private float textFount = 16; 
     @Override
     protected void onDrawScheme(Canvas canvas, Calendar calendar, int x, int y) { 
        float radius = 0.14f * mItemWidth; 
        float leftX = x + widthGapRadio * mItemWidth;
         float topY = y + heightGapRadio * mItemHeight;
         float rightX = x + (1 - widthGapRadio) * mItemWidth;
         float bottomY = y + (1 - heightGapRadio) * mItemHeight; 
         Path path = new Path();
         //起点,顶部横线左侧
         path.moveTo(leftX + radius, topY);
         //绘制顶部横线
         path.lineTo(rightX - radius, topY);
         //右上角圆弧
         path.quadTo(rightX, topY, rightX, topY + radius);
         //右侧横线
         path.lineTo(rightX, bottomY - radius);
         //右下角圆弧
         path.quadTo(rightX, bottomY, rightX - radius, bottomY);
         //底部横线
         path.lineTo(leftX + radius, bottomY);
         //左下圆弧
         path.quadTo(leftX, bottomY, leftX, bottomY - radius);
         //左侧横线
         path.lineTo(leftX, topY + radius);
         //左上圆弧
         path.quadTo(leftX, topY, leftX + radius, topY);
         //封闭子图形
         path.close();
         canvas.drawPath(path, mSchemePaint);
     } 
    @SuppressWarnings("IntegerDivisionInFloatingPointContext")
     @Override
     protected void onDrawText(Canvas canvas, Calendar calendar, int x, int y, boolean hasScheme, boolean isSelected) {
         float textLength = getDefaultTextPaint().measureText(String.valueOf(calendar.getDay()));
         int cx = x + mItemWidth / 2 - (int) textLength/2;
         int top = y ;
         mSchemePaint.getColor();
         Log.v("onDrawText", "mSchemePaint.getColor() = " + mSchemePaint.getColor());
         calendar.getScheme();
         Log.v("onDrawText", "calendar.getScheme() = " + calendar.getScheme());
         //Calendar.Scheme 指定文字颜色,若未制定,取默认颜色
         List<Calendar.Scheme> schemes = calendar.getSchemes();
        // calendar.getLunar()
         if (schemes == null || schemes.isEmpty()) {
             canvas.drawText(String.valueOf(calendar.getDay()), cx , mTextBaseLine + top,
             getDefaultTextPaint());
         } else {
             Calendar.Scheme scheme = schemes.get(0);
             canvas.drawText(String.valueOf(calendar.getDay()), cx, mTextBaseLine + top,
             getColorPaint(scheme.getShcemeColor()));
         }
      } 
       Map<Integer,Paint> catchPaint = new HashMap<>();
       private Paint getColorPaint(int shcemeColor) {
       Paint paint = catchPaint.get(shcemeColor);
       if (paint != null){
           return paint;
       }else {
           paint = new Paint();
           paint.setColor(shcemeColor);
           paint.setTextSize(AppUtils.dip2Px(getContext(),textFount));
           catchPaint.put(shcemeColor,paint);
           return paint;
         }
     } 
    Paint defaultPaint ;
         private Paint getDefaultTextPaint(){
             if (defaultPaint != null){
                 return defaultPaint;
             }else {
                 defaultPaint = new Paint();
                 defaultPaint.setColor(-0x666666);
                 defaultPaint.setTextSize(AppUtils.dip2Px(getContext(),textFount));
                 return defaultPaint;
             }
         }
}

1.背景自定义

自定义背景在此方法中

protected void onDrawScheme(Canvas canvas, Calendar calendar, int x, int y) {}

这里涉及了Path、Paint的几个重要方法和属性

//起点移动到指定位置 path.moveTo(leftX + radius, topY); //绘制横线,起点为上次的重点,这里的参数只需指定终点即可 path.lineTo(rightX - radius, topY); //绘制贝塞尔曲线,前两个参数为控制点,后两个参数为终点 path.quadTo(rightX, topY, rightX, topY + radius);` //封闭子图形 path.close();

paint设置为

mSchemePaint.setAntiAlias(true);
mSchemePaint.setStyle(Paint.Style.FILL);
mSchemePaint.setStrokeWidth(2);

绘制区域,封闭区域内都会被覆盖指定颜色

canvas.drawPath(path, mSchemePaint);

2.文字自定义

绘制文字为此方法

protected void onDrawText(Canvas canvas, Calendar calendar, int x, int y, boolean hasScheme, boolean isSelected) {}

这里的CalendarView的设计,在绘制背景的时候,会有参数指定背景的颜色值,背景的形状自己去定义;然而在绘制文字的时候,却是使用预定义的三种文字颜色。

这种设计可以满足大多数情况的要求,一般来说,我们对背景的样式会有更多的要求,而文字一般会根据背景是否选中情况展示黑白两种颜色以增强对比度。

而我们的设计要求是,选中的样式都是一致的,然而在选中的样式中,还有一些受关注的选中状态,这种区别我们期望通过文字的方式凸显出来。虽然CalendarView控件本身没提供便捷的方式进行设置,然而它却通过设置Scheme的方式保留了这种开放性。

private fun getSchemeCalendar(
 year: Int,
 month: Int,
 day: Int,
 type: Int
): Calendar {
 val calendar = Calendar()
 calendar.year = year
 calendar.month = month
 calendar.day = day
 calendar.schemeColor = -0x001c1d //背景颜色,CalendarView实现中已经将其设置给了画笔
 val schemes: MutableList<Scheme> = ArrayList()
 val scheme = Scheme()
 scheme.scheme = "test"
 scheme.type = type
 if (type ==2){
 scheme.shcemeColor = -0x27B8BA//指定schema的颜色,这个需要在自定义的view中取出使用
 }else{
 scheme.shcemeColor = -0xCCCCCC
 }
 schemes.add(scheme)
 calendar.schemes = schemes
 return calendar
}

scheme约束使用

3.点击事件

calendarView.setOnCalendarSelectListener(object :
 CalendarView.OnCalendarSelectListener {
 override fun onCalendarOutOfRange(calendar: Calendar?) {
 Log.v("vhawk","onCalendarOutOfRange calendar = ${calendar} ")
 }

 override fun onCalendarSelect(calendar: Calendar?, isClick: Boolean) {
 Log.v("vhawk","onCalendarSelect calendar = ${calendar} ${isClick}")
 }
})

后继

进一步了解CalendarView的细节,学习其中的设计思路

相关文章

  • CalendarView使用笔记

    背景 遇到一个需求,自定义一个日历。日历有两种背景展示,文字有三种颜色 于是github上找了一个满足条件且sta...

  • Hello CalendarView —— 日历使用

    一个很棒很漂亮的日历,感谢作者的开源。https://github.com/huanghaibin-dev/Cal...

  • Android CalendarView 使用示例

    定义布局文件: 主程序文件代码: 本示例的运行效果: 参考文献:《疯狂Android讲义(第2版)》

  • GitHub开源库CalendarView的使用

    学习并记录一下,使用GitHub上面的日历控件开源库CalendarView,地址:https://github....

  • CalendarView

    上下滑动的日历筛选控件,适合用在对话框dialog中 github地址:https://github.com/ti...

  • 日历视图使用

    目录 CalenderView CalendarView是安卓自带的一个日历控件, 可以使用其开发手机日历的相关功...

  • Android字体属性Paint.FontMetrics

    前言 最近在做需求的时候需要一个日历控件,在github上看CalendarView不错,UI部分完全可以由使用者...

  • 好的 demo

    日历:https://github.com/huanghaibin-dev/CalendarView 控件集合de...

  • 十五、Android用到的View补充

    首先列出补充的View:CalendarView:日历视图GridView:网格视图SearchView:搜索视图...

  • Android自带的好用的控件

    1》 NumberPicker好用的选择控件(滚轮效果) {参 考博客} 2》CalendarView: http...

网友评论

      本文标题:CalendarView使用笔记

      本文链接:https://www.haomeiwen.com/subject/qqycdrtx.html