# CalendarView **Repository Path**: deviche/CalendarView ## Basic Information - **Project Name**: CalendarView - **Description**: Android上一个优雅、万能自定义UI、支持周视图、自定义周起始、性能高效的日历控件,支持热插拔实现的UI定制!支持标记、自定义颜色、农历、自定义月视图各种显示模式等。Canvas绘制,速度快、占用内存低,你真的想不到日历居然还可以如此优雅!An elegant, highly customized and high-performance Calendar Widget on Android. - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2018-08-27 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # CalenderView Android上一个优雅、高度自定义、性能高效的日历控件,完美支持周视图,支持标记、自定义颜色、农历等,任意控制月视图显示、任意日期拦截条件、自定义周起始等。Canvas绘制,极速性能、占用内存低,,支持简单定制即可实现任意自定义布局、自定义UI,支持收缩展开、性能非常高效, 这个控件内存和效率优势相当明显,而且真正做到收缩+展开,适配多种场景,支持同时多种颜色标记日历事务,支持多点触控,你真的想不到日历还可以如此优雅!更多参考用法请移步Demo,Demo实现了4个精美的自定义效果。 ### Support English Version [**English Version**](https://github.com/huanghaibin-dev/CalendarView/blob/master/README_EN.md) ### Gradle ``` compile 'com.haibin:calendarview:3.4.3' ``` ``` com.haibin calendarview 3.4.3 pom ``` ### 列举一些常用的是否支持的问题 > * 是否支持周末等颜色单独?支持的,需要你自定义MonthView,WeekView,Calendar.isWeekend()可以自行判断是否周末,使用对应的画笔即可 > * 是否支持与其他控件联动?支持的,假如你喜欢小米的日历日期快速跳转,那么你也可以使用类似的控件通过调用各种 CalendarView.scrollToCalendar(); 函数即可 > * 是否支持日期长按?支持的,长按回调你可以做一些诸如声音、震动效果,框架并不提供,不利于解耦 > * 是否支持用图片作为点击效果?支持的,但你需要会drawBitmap > * 是否支持网格显示?当然是支持的,看你怎么绘制 > * 是否支持日期拦截?日期可用绘制?支持的,可以自行写拦截条件即可,支持拦截点击、滚动、和绘制任意日期 > * 是否支持自定义周起始?支持的,你可以定制周一、周日、周六为视图起始时间,使用 week_start_with attr > * 是否支持WeekBar星期栏与日期联动?支持的,你需要自定义WeekBar,实现 onDateSelected(Calendar calendar,int weekStart, boolean isClick);函数即可 > * 因此,只要在MonthView、WeekView里面出现的UI,什么五角星、贝塞尔曲线、图片等等,都是支持的,只要你会绘制,UI美不美,真的就看你了 ### 混淆proguard-rules ```java -keepclasseswithmembers class * { public (android.content.Context); } ``` ### 或者针对性的使用混淆 ``` java -keep class your project path.MonthView { public (android.content.Context); } -keep class your project path.WeekBar { public (android.content.Context); } -keep class your project path.WeekView { public (android.content.Context); } ``` ### 完整用法教程请参照博客教程 [**https://juejin.im/post/5a6743836fb9a01caa20aefc**](https://juejin.im/post/5a6743836fb9a01caa20aefc) ### 如果你需要完全定制UI,参考demo,简单几步即可绘制你需要的效果,一般只需要实现三个回调函数绘制你需要的特效即可,自定义日历UI需要同时自定义周视图,真正做到热插拔效果,方便大众定制各种UI需求 ### 效果预览 ### 功能性展示       ### 中国式变态需求风格       ### 收缩展开的魅族风格效果       ### 下标和多彩风格       ### 进度条风格       ### 星系图风格       ### 快速年份月份切换       ### 特别的,请注意不要复制这三个路径,自行替换您自己的自定义路径 ```xml app:month_view="com.haibin.calendarviewproject.simple.SimpleCalendarCardView" app:week_view="com.haibin.calendarviewproject.simple.SimpleWeekView" app:week_bar_view="com.haibin.calendarviewproject.EnglishWeekBar" ``` ### 使用方法 ```xml ``` ### CalendarView attrs ```xml                       ``` ### CalendarView api ```java public void setRange(int minYear, int minYearMonth, int minYearDay, int maxYear, int maxYearMonth, int maxYearDay) ;//置日期范围 public int getCurDay(); //今天 public int getCurMonth(); //当前的月份 public int getCurYear(); //今年 public boolean isYearSelectLayoutVisible();//年月份选择视图是否打开 public void closeYearSelectLayout();//关闭年月视图选择布局 public void showYearSelectLayout(final int year); //快速弹出年份选择月份 public void setOnMonthChangeListener(OnMonthChangeListener listener);//月份改变事件 public void setOnYearChangeListener(OnYearChangeListener listener);//年份切换事件 public void setOnCalendarSelectListener(OnCalendarSelectListener listener)//日期选择事件 public void setOnCalendarLongClickListener(OnCalendarLongClickListener listener);//日期长按事件 public void setOnCalendarLongClickListener(OnCalendarLongClickListener listener, boolean preventLongPressedSelect);//日期长按事件 public void setOnCalendarInterceptListener(OnCalendarInterceptListener listener);//日期拦截和日期有效性绘制 public void setSchemeDate(Map mSchemeDates);//标记日期 public void update();//动态更新 public Calendar getSelectedCalendar(); //获取选择的日期 /** * 特别的,如果你需要自定义或者使用其它选择器,可以用以下方法进行和日历联动 */ public void scrollToCurrent();//滚动到当前日期 public void scrollToCurrent(boolean smoothScroll);//滚动到当前日期 public void scrollToYear(int year);//滚动到某一年 public void scrollToPre();//滚动到上一个月 public void scrollToNext();//滚动到下一个月 public void scrollToCalendar(int year, int month, int day);//滚动到指定日期 public Calendar getMinRangeCalendar();//获得最小范围日期 public Calendar getMaxRangeCalendar();//获得最大范围日期 /** * 设置背景色 * * @param monthLayoutBackground 月份卡片的背景色 * @param weekBackground 星期栏背景色 * @param lineBg 线的颜色 */ public void setBackground(int monthLayoutBackground, int weekBackground, int lineBg) /** * 设置文本颜色 * * @param curMonthTextColor 当前月份字体颜色 * @param otherMonthColor 其它月份字体颜色 * @param lunarTextColor 农历字体颜色 */ public void setTextColor(int curMonthTextColor,int otherMonthColor,int lunarTextColor) /** * 设置选择的效果 * * @param style 选中的style CalendarCardView.STYLE_FILL or CalendarCardView.STYLE_STROKE * @param selectedThemeColor 选中的标记颜色 * @param selectedTextColor 选中的字体颜色 */ public void setSelectedColor(int style, int selectedThemeColor, int selectedTextColor) /** * 设置标记的色 * * @param style 标记的style CalendarCardView.STYLE_FILL or CalendarCardView.STYLE_STROKE * @param schemeColor 标记背景色 * @param schemeTextColor 标记字体颜色 */ public void setSchemeColor(int style, int schemeColor, int schemeTextColor) /** * 设置星期栏的背景和字体颜色 * * @param weekBackground 背景色 * @param weekTextColor 字体颜色 */ public void setWeeColor(int weekBackground, int weekTextColor) ``` ### CalendarLayout api ```java public void expand(); //展开 public void shrink(); //收缩 public boolean isExpand();//是否展开了 ``` ### CalendarLayout attrs ```xml ``` ### 如果你需要完全定制UI,参考demo,简单几步即可绘制你需要的效果,月视图和周视图需要同时更换,达到UI一致 #### 首先绘制月视图 ```java public class SimpleCalendarCardView extends MonthView { private int mRadius; public SimpleCalendarCardView(Context context) { super(context); } @Override protected void onPreviewHook() { mRadius = Math.min(mItemWidth, mItemHeight) / 5 * 2; mSchemePaint.setStyle(Paint.Style.STROKE); } @Override protected void onLoopStart(int x, int y) { } @Override protected boolean onDrawSelected(Canvas canvas, Calendar calendar, int x, int y, boolean hasScheme) { int cx = x + mItemWidth / 2; int cy = y + mItemHeight / 2; canvas.drawCircle(cx, cy, mRadius, mSelectedPaint); return false; } @Override protected void onDrawScheme(Canvas canvas, Calendar calendar, int x, int y) { int cx = x + mItemWidth / 2; int cy = y + mItemHeight / 2; canvas.drawCircle(cx, cy, mRadius, mSchemePaint); } @Override protected void onDrawText(Canvas canvas, Calendar calendar, int x, int y, boolean hasScheme, boolean isSelected) { float baselineY = mTextBaseLine + y; int cx = x + mItemWidth / 2; if (hasScheme) { canvas.drawText(String.valueOf(calendar.getDay()), cx, baselineY, calendar.isCurrentDay() ? mCurDayTextPaint : calendar.isCurrentMonth() ? mSchemeTextPaint : mOtherMonthTextPaint); } else { canvas.drawText(String.valueOf(calendar.getDay()), cx, baselineY, calendar.isCurrentDay() ? mCurDayTextPaint : calendar.isCurrentMonth() ? mCurMonthTextPaint : mOtherMonthTextPaint); } } } ``` #### 其次绘制周视图,周视图回调几乎一样,唯一的区别是不需要y,只有一行,所以可以直接拷贝代码,把y=0即可 ```java public class SimpleWeekView extends WeekView{ private int mRadius; public SimpleWeekView(Context context) { super(context); } @Override protected void onPreviewHook() { mRadius = Math.min(mItemWidth, mItemHeight) / 5 * 2; mSchemePaint.setStyle(Paint.Style.STROKE); } @Override protected boolean onDrawSelected(Canvas canvas, Calendar calendar, int x, boolean hasScheme) { int cx = x + mItemWidth / 2; int cy = mItemHeight / 2; canvas.drawCircle(cx, cy, mRadius, mSelectedPaint); return false } @Override protected void onDrawScheme(Canvas canvas, Calendar calendar, int x) { int cx = x + mItemWidth / 2; int cy = mItemHeight / 2; canvas.drawCircle(cx, cy, mRadius, mSchemePaint); } @Override protected void onDrawText(Canvas canvas, Calendar calendar, int x, boolean hasScheme, boolean isSelected) { float baselineY = mTextBaseLine ; int cx = x + mItemWidth / 2; if (hasScheme) { canvas.drawText(String.valueOf(calendar.getDay()), cx, baselineY, calendar.isCurrentDay() ? mCurDayTextPaint : calendar.isCurrentMonth() ? mSchemeTextPaint : mSchemeTextPaint); } else { canvas.drawText(String.valueOf(calendar.getDay()), cx, baselineY, calendar.isCurrentDay() ? mCurDayTextPaint : calendar.isCurrentMonth() ? mCurMonthTextPaint : mCurMonthTextPaint); } } } ``` ### 写在结尾:这个控件。只需要懂得一点Canvas的知识即可,如果你是新手,那么你可以通过此控件获得提升,此项目代码注释完善,结构也很简单,逻辑没那么复杂。这个项目是十分解耦合的,自定义WeekBar,MonthView、WeekView都是可以的,如果想和其它控件嵌套使用,外部父控件事件冲突可以自由通过CalendarLayout.isExpand();解决,内部基本没有事件冲突 ### 个人不做什么打赏,不搞QQ群,如果帮助你解决了问题,请给个star就好。 ## Licenses - Copyright (C) 2013 huanghaibin_dev - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and limitations under the License.