当前位置:   article > 正文

Android自定义日历功能_android 自定义日历

android 自定义日历

背景

        Android开发,经常会使用到日历开发,实现方式有自定义或者第三方框架基础上修改。这里推荐使用第三方框架基础上修改。com.haibin.calendarview.CalendarView,为此本demo亦是在此框架基础上自定义样式,实现理想的日历。实现的功能有:

        1、自定义星期标题

        2、标记对应日程提醒,如图日期提醒标记---铃铛

        3、节假日与节气文字自定义

        4、自定义日历两边文字显色,例如星期日与星期六那两列的公历日期文字为淡红色

        5、自定义日历网格线

效果如下图

一、日历框架属性基本介绍

    1.依赖

  1. //日历 android 引入
  2. implementation 'com.haibin:calendarview:3.6.8'
  3. //日历 androidx 引入
  4. implementation 'com.haibin:calendarview:3.7.1'

    2.属性介绍

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <resources>
  3. <declare-styleable name="CalendarView">
  4. <attr name="calendar_padding" format="dimension" /><!--日历内部左右padding-->
  5. <attr name="calendar_padding_left" format="dimension" /><!--日历内部左padding-->
  6. <attr name="calendar_padding_right" format="dimension" /><!--日历内部右padding-->
  7. <attr name="week_background" format="color" /><!--周背景-->
  8. <attr name="week_line_background" format="color" /><!--线条颜色-->
  9. <attr name="week_text_color" format="color" /><!--周栏字体颜色-->
  10. <attr name="week_text_size" format="dimension" /><!--周栏字体大小-->
  11. <attr name="week_line_margin" format="dimension" /><!--线条margin-->
  12. <attr name="month_view" format="string" /><!--完全自定义月视图-->
  13. <attr name="week_view" format="string" /> <!--完全自定义周视图-->
  14. <attr name="year_view" format="string" /> <!--完全自定义年视图-->
  15. <attr name="week_bar_height" format="dimension" /> <!--星期栏的高度-->
  16. <attr name="week_bar_view" format="string" /> <!--如果需要的话使用自定义星期栏-->
  17. <attr name="scheme_text" format="string" />
  18. <attr name="day_text_size" format="dimension" />
  19. <attr name="lunar_text_size" format="dimension" />
  20. <attr name="calendar_height" format="dimension" />
  21. <attr name="calendar_match_parent" format="boolean" /> <!-- 全屏日历 -->
  22. <attr name="scheme_text_color" format="color" />
  23. <attr name="scheme_month_text_color" format="color" />
  24. <attr name="scheme_lunar_text_color" format="color" />
  25. <attr name="scheme_theme_color" format="color" />
  26. <attr name="selected_theme_color" format="color" />
  27. <attr name="selected_text_color" format="color" />
  28. <attr name="selected_lunar_text_color" format="color" />
  29. <attr name="current_day_text_color" format="color" />
  30. <attr name="current_day_lunar_text_color" format="color" />
  31. <attr name="current_month_text_color" format="color" />
  32. <attr name="other_month_text_color" format="color" />
  33. <attr name="current_month_lunar_text_color" format="color" />
  34. <attr name="other_month_lunar_text_color" format="color" />
  35. <!-- 年视图相关 -->
  36. <attr name="year_view_month_text_size" format="dimension" />
  37. <attr name="year_view_day_text_size" format="dimension" />
  38. <attr name="year_view_month_text_color" format="color" />
  39. <attr name="year_view_current_day_text_color" format="color" />
  40. <attr name="year_view_day_text_color" format="color" />
  41. <attr name="year_view_select_text_color" format="color" />
  42. <attr name="year_view_scheme_color" format="color" />
  43. <attr name="year_view_background" format="color" />
  44. <attr name="year_view_month_height" format="dimension" />
  45. <attr name="year_view_week_height" format="dimension" />
  46. <attr name="year_view_week_text_size" format="dimension" />
  47. <attr name="year_view_week_text_color" format="color" />
  48. <attr name="year_view_padding" format="dimension" />
  49. <attr name="year_view_padding_left" format="dimension" />
  50. <attr name="year_view_padding_right" format="dimension" />
  51. <attr name="year_view_month_padding_top" format="dimension" />
  52. <attr name="year_view_month_padding_left" format="dimension" />
  53. <attr name="year_view_month_padding_right" format="dimension" />
  54. <attr name="year_view_month_padding_bottom" format="dimension" />
  55. <!--日期范围-->
  56. <attr name="min_year" format="integer" />
  57. <attr name="max_year" format="integer" />
  58. <attr name="min_year_month" format="integer" />
  59. <attr name="max_year_month" format="integer" />
  60. <attr name="min_year_day" format="integer" />
  61. <attr name="max_year_day" format="integer" />
  62. <!--月视图是否可滚动-->
  63. <attr name="month_view_scrollable" format="boolean" />
  64. <!--周视图是否可滚动-->
  65. <attr name="week_view_scrollable" format="boolean" />
  66. <!--年视图是否可滚动-->
  67. <attr name="year_view_scrollable" format="boolean" />
  68. <!-- 月份显示模式 -->
  69. <attr name="month_view_show_mode">
  70. <enum name="mode_all" value="0" />
  71. <enum name="mode_only_current" value="1" />
  72. <enum name="mode_fix" value="2" />
  73. </attr>
  74. <!-- 自定义周起始 -->
  75. <attr name="week_start_with">
  76. <enum name="sun" value="1" />
  77. <enum name="mon" value="2" />
  78. <enum name="sat" value="7" />
  79. </attr>
  80. <!-- 自定义选择模式 -->
  81. <attr name="select_mode">
  82. <enum name="default_mode" value="0" />
  83. <enum name="single_mode" value="1" />
  84. <enum name="range_mode" value="2" />
  85. <enum name="multi_mode" value="3" />
  86. </attr>
  87. <!-- when select_mode = multi_mode -->
  88. <attr name="max_multi_select_size" format="integer" />
  89. <!-- when select_mode = range_mode -->
  90. <attr name="min_select_range" format="integer" />
  91. <attr name="max_select_range" format="integer" />
  92. <!-- auto select day -->
  93. <attr name="month_view_auto_select_day">
  94. <enum name="first_day_of_month" value="0" />
  95. <enum name="last_select_day" value="1" />
  96. <enum name="last_select_day_ignore_current" value="2" />
  97. </attr>
  98. </declare-styleable>
  99. <declare-styleable name="CalendarLayout">
  100. <attr name="default_status">
  101. <enum name="expand" value="0" />
  102. <enum name="shrink" value="1" />
  103. </attr>
  104. <!-- 手势模式 -->
  105. <attr name="gesture_mode">
  106. <enum name="default_mode" value="0" />
  107. <!--<enum name="only_calendar" value="1" />-->
  108. <enum name="disabled" value="2" />
  109. </attr>
  110. <attr name="calendar_show_mode">
  111. <enum name="both_month_week_view" value="0" />
  112. <enum name="only_week_view" value="1" />
  113. <enum name="only_month_view" value="2" />
  114. </attr>
  115. <attr name="calendar_content_view_id" format="integer" />
  116. </declare-styleable>
  117. </resources>

二、本demo实现步骤

1.依赖

  1. //日历 android 引入
  2. implementation 'com.haibin:calendarview:3.6.8'
  3. //日历 androidx 引入
  4. implementation 'com.haibin:calendarview:3.7.1'

2.xml布局

  1. <com.haibin.calendarview.CalendarView
  2. android:id="@+id/mCalendarView"
  3. android:layout_width="416dp"
  4. android:layout_height="@dimen/dimen_322"
  5. android:layout_marginLeft="@dimen/dp_2"
  6. android:layout_marginRight="@dimen/dp_2"
  7. android:layout_marginBottom="@dimen/dp_2"
  8. android:background="@drawable/data_cl_bg"
  9. app:calendar_height="@dimen/dp_50"
  10. app:current_day_lunar_text_color="#2856AC"
  11. app:current_day_text_color="#2856AC"
  12. app:min_year="2023"
  13. app:month_view="csu.xiaoya.robotApp.ui.activity.homepage.calendar.CustomMonthView"
  14. app:other_month_lunar_text_color="@color/white"
  15. app:other_month_text_color="@color/white"
  16. app:scheme_lunar_text_color="@color/color_grey_9"
  17. app:scheme_text_color="@color/color333"
  18. app:select_mode="default_mode"
  19. app:selected_lunar_text_color="@color/white"
  20. app:selected_text_color="@color/white"
  21. app:selected_theme_color="#4868C3"
  22. app:week_background="#172B7C"
  23. app:week_bar_height="@dimen/dp_24"
  24. app:week_bar_view="csu.xiaoya.robotApp.ui.activity.homepage.calendar.CustomWeekBar"
  25. app:week_text_color="@color/white" />

由于自定义view跟日历界面在同一目录下

     

   故引用如下:

    app:month_view="csu.xiaoya.robotApp.ui.activity.homepage.calendar.CustomMonthView"

    app:week_bar_view="csu.xiaoya.robotApp.ui.activity.homepage.calendar.CustomWeekBar"
 

 3.自定义month_view ,类名CustomMonthView

  1. /**
  2. * 标记
  3. * 节假日与节气
  4. */
  5. public class CustomMonthView extends MonthView {
  6. private int mRadius;
  7. /**
  8. * 自定义魅族标记的文本画笔
  9. */
  10. private Paint mTextPaint = new Paint();
  11. /**
  12. * 24节气与
  13. * 节假日画笔
  14. */
  15. private Paint mSolarTermTextPaint = new Paint();
  16. /**
  17. * 网格画笔
  18. */
  19. private Paint mRectPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
  20. /**
  21. * 背景圆点
  22. */
  23. private Paint mPointPaint = new Paint();
  24. /**
  25. * 今天的背景色
  26. */
  27. private Paint mCurrentDayPaint = new Paint();
  28. /**
  29. * 圆点半径
  30. */
  31. private float mPointRadius;
  32. private int mPadding;
  33. private float mCircleRadius;
  34. /**
  35. * 自定义背景
  36. */
  37. private Paint mSchemeBasicPaint = new Paint();
  38. private float mSchemeBaseLine;
  39. private int currentMonth = 0;//当前月份
  40. public CustomMonthView(Context context) {
  41. super(context);
  42. mTextPaint.setTextSize(dipToPx(context, 8));
  43. mTextPaint.setColor(0xffffffff);
  44. mTextPaint.setAntiAlias(true);
  45. mTextPaint.setFakeBoldText(true);
  46. //* Typeface.BOLD //粗体
  47. //* Typeface.BOLD_ITALIC //粗斜体
  48. //* Typeface.ITALIC //斜体
  49. //* Typeface.NORMAL //常规
  50. mSolarTermTextPaint.setColor(0xffE92F3A);
  51. Typeface font = Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD);
  52. mSolarTermTextPaint.setTypeface(font);
  53. mSolarTermTextPaint.setAntiAlias(true);
  54. mSolarTermTextPaint.setTextAlign(Paint.Align.CENTER);
  55. mSchemeBasicPaint.setAntiAlias(true);
  56. mSchemeBasicPaint.setStyle(Paint.Style.FILL);
  57. mSchemeBasicPaint.setTextAlign(Paint.Align.CENTER);
  58. mSchemeBasicPaint.setFakeBoldText(true);
  59. mSchemeBasicPaint.setColor(Color.parseColor("#00ffffff"));
  60. mCurrentDayPaint.setAntiAlias(true);
  61. mCurrentDayPaint.setStyle(Paint.Style.FILL);
  62. mCurrentDayPaint.setColor(0xFFffffff);
  63. mPointPaint.setAntiAlias(true);
  64. mPointPaint.setStyle(Paint.Style.FILL);
  65. mPointPaint.setTextAlign(Paint.Align.CENTER);
  66. mPointPaint.setColor(Color.RED);
  67. mRectPaint.setStyle(Paint.Style.STROKE);
  68. mRectPaint.setStrokeWidth(dipToPx(context, 0.5f));
  69. mRectPaint.setColor(0x88DBDDE4);
  70. mCircleRadius = dipToPx(getContext(), 7);
  71. mPadding = dipToPx(getContext(), 8);
  72. mPointRadius = dipToPx(context, 2);
  73. Paint.FontMetrics metrics = mSchemeBasicPaint.getFontMetrics();
  74. mSchemeBaseLine = mCircleRadius - metrics.descent + (metrics.bottom - metrics.top) / 2 + dipToPx(getContext(), 1);
  75. }
  76. @Override
  77. protected void onPreviewHook() {
  78. mSolarTermTextPaint.setTextSize(mCurMonthLunarTextPaint.getTextSize());
  79. mRadius = Math.min(mItemWidth, mItemHeight) / 11 * 5;
  80. }
  81. @Override
  82. protected boolean onDrawSelected(Canvas canvas, Calendar calendar, int x, int y, boolean hasScheme) {
  83. int cx = x + mItemWidth * 1;
  84. int cy = y + mItemHeight * 1;
  85. canvas.drawRect(x, y, cx, cy, mSelectedPaint);
  86. // canvas.drawCircle(cx, cy, mRadius, mSelectedPaint);
  87. return true;
  88. }
  89. @Override
  90. protected void onDrawScheme(Canvas canvas, Calendar calendar, int x, int y) {
  91. // boolean isSelected = isSelected(calendar);
  92. // if (isSelected) {
  93. // mPointPaint.setColor(Color.WHITE);
  94. // } else {
  95. // mPointPaint.setColor(Color.BLUE);
  96. // }
  97. // canvas.drawCircle(x + mItemWidth / 2, y + mItemHeight - 3 * mPadding, mPointRadius, mPointPaint);
  98. }
  99. @SuppressWarnings("IntegerDivisionInFloatingPointContext")
  100. @Override
  101. protected void onDrawText(Canvas canvas, Calendar calendar, int x, int y, boolean hasScheme, boolean isSelected) {
  102. int cx = x + mItemWidth / 2;
  103. int cy = y + mItemHeight / 2;
  104. int top = y - mItemHeight / 6;
  105. canvas.drawRect(x, y, x + mItemWidth, y + mItemHeight, mRectPaint);
  106. if (hasScheme) {
  107. canvas.drawCircle(x + mItemWidth - mPadding - mCircleRadius / 2, y + mPadding + mCircleRadius, mCircleRadius, mSchemeBasicPaint);
  108. mTextPaint.setColor(calendar.getSchemeColor());
  109. //可通过修改坐标值调整tag位置
  110. canvas.drawText(calendar.getScheme(), x + mItemWidth - mPadding - mCircleRadius, y + mPadding + mSchemeBaseLine-16, mTextPaint);
  111. }
  112. //当然可以换成其它对应的画笔就不麻烦,
  113. if (calendar.isWeekend() && calendar.isCurrentMonth()) {
  114. mCurMonthTextPaint.setColor(0xFFE30003);
  115. mCurMonthLunarTextPaint.setColor(0xFF999999);
  116. mSchemeTextPaint.setColor(0xFFE30003);
  117. mSchemeLunarTextPaint.setColor(0xFF999999);
  118. // mOtherMonthLunarTextPaint.setColor(0xFF489dff);
  119. // mOtherMonthTextPaint.setColor(0xFF489dff);
  120. } else {
  121. mCurMonthTextPaint.setColor(0xff333333);
  122. mCurMonthLunarTextPaint.setColor(0xFF999999);
  123. mSchemeTextPaint.setColor(0xff333333);
  124. mSchemeLunarTextPaint.setColor(0xFF999999);
  125. // mOtherMonthTextPaint.setColor(0xFFe1e1e1);
  126. // mOtherMonthLunarTextPaint.setColor(0xFFe1e1e1);
  127. }
  128. // Log.d("节假日", "======onDrawText: =======" + calendar.getTraditionFestival());
  129. if (isSelected) {
  130. canvas.drawText(String.valueOf(calendar.getDay()), cx, mTextBaseLine + top, mSelectTextPaint);
  131. canvas.drawText(calendar.getLunar(), cx, mTextBaseLine + y + mItemHeight / 10, mSelectedLunarTextPaint);
  132. } else if (hasScheme) {
  133. canvas.drawText(String.valueOf(calendar.getDay()), cx, mTextBaseLine + top, calendar.isCurrentMonth() ? mSchemeTextPaint : mOtherMonthTextPaint);
  134. canvas.drawText(calendar.getLunar(), cx, mTextBaseLine + y + mItemHeight / 10, !TextUtils.isEmpty(calendar.getSolarTerm() + calendar.getTraditionFestival() + calendar.getGregorianFestival()) ? mSolarTermTextPaint : mSchemeLunarTextPaint);
  135. } else {
  136. canvas.drawText(String.valueOf(calendar.getDay()), cx, mTextBaseLine + top, calendar.isCurrentDay() ? mCurDayTextPaint : calendar.isCurrentMonth() ? mCurMonthTextPaint : mOtherMonthTextPaint);
  137. canvas.drawText(calendar.getLunar(), cx, mTextBaseLine + y + mItemHeight / 10, calendar.isCurrentDay() ? mCurDayLunarTextPaint : calendar.isCurrentMonth() ? !TextUtils.isEmpty(calendar.getSolarTerm() + calendar.getTraditionFestival() + calendar.getGregorianFestival()) ? mSolarTermTextPaint : mCurMonthLunarTextPaint : mOtherMonthLunarTextPaint);
  138. }
  139. //当日
  140. if (calendar.isCurrentDay() && !calendar.isCurrentMonth()) {
  141. canvas.drawCircle(cx, cy, mRadius, mCurrentDayPaint);
  142. canvas.drawText(String.valueOf(calendar.getDay()), cx, cy, mCurrentDayPaint);
  143. }
  144. }
  145. /**
  146. * dp转px
  147. *
  148. * @param context context
  149. * @param dpValue dp
  150. * @return px
  151. */
  152. private static int dipToPx(Context context, float dpValue) {
  153. final float scale = context.getResources().getDisplayMetrics().density;
  154. return (int) (dpValue * scale + 0.5f);
  155. }
  156. }

4.自定义周标题week_bar_view,类名CustomWeekBar

  1. /**
  2. * 自定义日历
  3. * 周布局
  4. */
  5. public class CustomWeekBar extends WeekBar {
  6. private int mPreSelectedIndex;
  7. public CustomWeekBar(Context context) {
  8. super(context);
  9. LayoutInflater.from(context).inflate(R.layout.custom_week_bar, this, true);
  10. setBackgroundColor(Color.WHITE);
  11. }
  12. @Override
  13. protected void onDateSelected(Calendar calendar, int weekStart, boolean isClick) {
  14. getChildAt(mPreSelectedIndex).setSelected(false);
  15. int viewIndex = getViewIndexByCalendar(calendar, weekStart);
  16. getChildAt(viewIndex).setSelected(true);
  17. mPreSelectedIndex = viewIndex;
  18. }
  19. /**
  20. * 当周起始发生变化,使用自定义布局需要重写这个方法,避免出问题
  21. *
  22. * @param weekStart 周起始
  23. */
  24. @Override
  25. protected void onWeekStartChange(int weekStart) {
  26. for (int i = 0; i < getChildCount(); i++) {
  27. ((TextView) getChildAt(i)).setText(getWeekString(i, weekStart));
  28. }
  29. }
  30. /**
  31. * 或者周文本,这个方法仅供父类使用
  32. *
  33. * @param index index
  34. * @param weekStart weekStart
  35. * @return 或者周文本
  36. */
  37. private String getWeekString(int index, int weekStart) {
  38. String[] weeks = getContext().getResources().getStringArray(R.array.chinese_week_string_array);
  39. if (weekStart == 1) {
  40. return weeks[index];
  41. }
  42. if (weekStart == 2) {
  43. return weeks[index == 6 ? 0 : index + 1];
  44. }
  45. return weeks[index == 0 ? 6 : index - 1];
  46. }
  47. }

 5. 设置日程消息提醒标记

  1. // 设置日程消息提醒标记
  2. Map<String, Calendar> map = new HashMap<>();
  3. map.put(getSchemeCalendar(2024, 2, 23, 0x00ffffff, "
    声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/543232
    推荐阅读
    相关标签