Android开源的精美日历控件,热插拔设计的万能自定义UI

时间:2021-12-28 00:07:22

Android开源的精美日历控件,热插拔设计的万能自定义UI

UI框架应该逻辑与界面实现分离,该日历控件使用了热插拔的设计 ,简单几步即可实现你需要的UI效果,热插拔的思想是你提供你的实现,我提供我的插座接口,与自定义Behavior是一样的思想。

CalendarView的优势:

1、热插拔设计,根据不同的UI需求完全自定义UI,简单几步即可实现,自定义事件日历标记、颜色、农历等

2、完全Canvas绘制,性能和速度都很不错,相比大多数基于GridView或RecyclerView实现的占用内存更低,启动速度更快

3、支持收缩、展开、快速年月份选择等

4、简洁易懂的源码,易学习。

先看看控件的attr

<declare-styleable name="CalendarView">

        <attr name="calendar_card_view" format="color" /> <!--热插拔自定义类路径-->

        <attr name="week_background" format="color" /> <!--星期栏的背景-->
<attr name="week_text_color" format="color" /> <!--星期栏文本颜色--> <attr name="current_day_text_color" format="color" /> <!--今天的文本颜色--> <attr name="day_text_size" format="string" /> <!--天数文本大小-->
<attr name="lunar_text_size" format="string" /> <!--农历文本大小--> <attr name="scheme_text" format="string" /> <!--标记文本-->
<attr name="scheme_text_color" format="color" /> <!--标记文本颜色-->
<attr name="scheme_month_text_color" format="color" /> <!--标记天数文本颜色-->
<attr name="scheme_lunar_text_color" format="color" /> <!--标记农历文本颜色--> <attr name="scheme_theme_color" format="color" /> <!--标记的颜色--> <attr name="selected_theme_color" format="color" /> <!--选中颜色-->
<attr name="selected_text_color" format="color" /> <!--选中文本颜色-->
<attr name="selected_lunar_text_color" format="color" /> <!--选中农历文本颜色--> <attr name="current_month_text_color" format="color" /> <!--当前月份的字体颜色-->
<attr name="other_month_text_color" format="color" /> <!--其它月份的字体颜色--> <attr name="current_month_lunar_text_color" format="color" /> <!--当前月份农历节假日颜色-->
<attr name="other_month_lunar_text_color" format="color" /> <!--其它月份农历节假日颜色--> <attr name="min_year" format="integer" /> <!--最小年份1900-->
<attr name="max_year" format="integer" /> <!--最大年份2099--> </declare-styleable>

XML用法

如果需要在日历控件下方使用其它控件,使用CalendarLayout控件即可,calendar_content_view_id为其它控件的id,支持任意控件,如RecyclerView、ListView。CalendarView的calendar_card_view为任意自定义实现的日历绘制控件路径。

<com.haibin.calendarview.CalendarLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#fff"
app:calendar_content_view_id="@+id/linearView"> <com.haibin.calendarview.CalendarView
android:id="@+id/calendarView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#fff"
app:current_month_text_color="#333333"
app:current_month_lunar_text_color="#CFCFCF"
app:min_year="2004"
app:other_month_text_color="#e1e1e1"
app:scheme_text_color="#333"
app:scheme_theme_color="#128c4b"
app:selected_lunar_text_color="#CFCFCF"
app:calendar_card_view="com.haibin.calendarviewproject.meizu.MeiZuCalendarCardView"
app:selected_text_color="#333"
app:selected_theme_color="#108cd4"
app:week_background="#fff"
app:week_text_color="#111" /> <LinearLayout
android:id="@+id/linearView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/content_background"
android:clickable="true"
android:orientation="vertical"
tools:ignore="KeyboardInaccessibleWidget"/>
</LinearLayout>
</com.haibin.calendarview.CalendarLayout>

熟悉一下这几个简单的特性,看看日历内容界面的绘制BaseCalendarCardView,根据需求实现以下部分方法即可

/**
* 开始绘制前的回调钩子,这里做一些初始化的操作,每次绘制只调用一次,性能高效
* 没有需要可忽略不实现
* 例如:
* 1、需要绘制圆形标记事件背景,可以在这里计算半径
* 2、绘制矩形选中效果,也可以在这里计算矩形宽和高
*/
protected void onPreviewHook() {
// TODO: 2017/11/16
} /**
* 循环绘制开始的回调,不需要可忽略
* 绘制每个日历项的循环,用来计算baseLine、圆心坐标等都可以在这里实现
*
* @param x 日历Card x起点坐标
* @param y 日历Card y起点坐标
*/
protected void onLoopStart(int x, int y) {
// TODO: 2017/11/16
} /**
* 绘制选中的日期
*
* @param canvas canvas
* @param calendar 日历日历calendar
* @param x 日历Card x起点坐标
* @param y 日历Card y起点坐标
* @param hasScheme hasScheme 非标记的日期
*/
protected abstract void onDrawSelected(Canvas canvas, Calendar calendar, int x, int y, boolean hasScheme); /**
* 绘制标记的日期UI
*
* @param canvas canvas
* @param calendar 日历calendar
* @param x 日历Card x起点坐标
* @param y 日历Card y起点坐标
*/
protected abstract void onDrawScheme(Canvas canvas, Calendar calendar, int x, int y); /**
* 绘制日历文本
*
* @param canvas canvas
* @param calendar 日历calendar
* @param x 日历Card x起点坐标
* @param y 日历Card y起点坐标
* @param hasScheme 是否是标记的日期
* @param isSelected 是否选中
*/
protected abstract void onDrawText(Canvas canvas, Calendar calendar, int x, int y, boolean hasScheme, boolean isSelected);

举个例子:如果你的需求是类似魅族日历的UI,那么第一步,继承BaseCalendarCardView,然后实现onDrawSelected、onDrawScheme、onDrawText三个回调函数即可

public class MeiZuCalendarCardView extends BaseCalendarCardView {

    private Paint mTextPaint = new Paint();
private Paint mSchemeBasicPaint = new Paint();
private float mRadio;
private int mPadding;
private float mSchemeBaseLine; public MeiZuCalendarCardView(Context context) {
super(context); mTextPaint.setTextSize(dipToPx(context, 8));
mTextPaint.setColor(0xff111111);
mTextPaint.setAntiAlias(true);
mTextPaint.setFakeBoldText(true); mSchemeBasicPaint.setAntiAlias(true);
mSchemeBasicPaint.setStyle(Paint.Style.FILL);
mSchemeBasicPaint.setTextAlign(Paint.Align.CENTER);
mSchemeBasicPaint.setColor(0xffed5353);
mSchemeBasicPaint.setFakeBoldText(true);
mRadio = dipToPx(getContext(), 7);
mPadding = dipToPx(getContext(), 4);
Paint.FontMetrics metrics = mSchemeBasicPaint.getFontMetrics();
mSchemeBaseLine = mRadio - metrics.descent + (metrics.bottom - metrics.top) / 2 + dipToPx(getContext(), 1); } /**
* 绘制选中的日期
*
* @param canvas canvas
* @param calendar 日历日历calendar
* @param x 日历Card x起点坐标
* @param y 日历Card y起点坐标
* @param hasScheme hasScheme 非标记的日期
*/
@Override
protected void onDrawSelected(Canvas canvas, Calendar calendar, int x, int y, boolean hasScheme) {
mSelectedPaint.setStyle(Paint.Style.FILL);
mSelectedPaint.setColor(0x80cfcfcf);
canvas.drawRect(x + mPadding, y + mPadding, x + mItemWidth - mPadding, y + mItemHeight - mPadding, mSelectedPaint);
} /**
* 绘制标记的日期UI 这里魅族界面不需要绘制多彩风格,忽略即可
*
* @param canvas canvas
* @param calendar 日历calendar
* @param x 日历Card x起点坐标
* @param y 日历Card y起点坐标
*/
@Override
protected void onDrawScheme(Canvas canvas, Calendar calendar, int x, int y) { } /**
* 绘制日历文本
*
* @param canvas canvas
* @param calendar 日历calendar
* @param x 日历Card x起点坐标
* @param y 日历Card y起点坐标
* @param hasScheme 是否是标记的日期
* @param isSelected 是否选中
*/
@Override
protected void onDrawText(Canvas canvas, Calendar calendar, int x, int y, boolean hasScheme, boolean isSelected) {
int cx = x + mItemWidth / 2;
int top = y - mItemHeight / 6;
if (hasScheme) {
//绘制日期
canvas.drawText(String.valueOf(calendar.getDay()), cx, mTextBaseLine + top,
calendar.isCurrentDay() ? mCurDayTextPaint :
calendar.isCurrentMonth() ? mSchemeTextPaint : mOtherMonthTextPaint);
//绘制农历
canvas.drawText(calendar.getLunar(), cx, mTextBaseLine + y + mItemHeight / 10, mCurMonthLunarTextPaint);
mTextPaint.setColor(Color.WHITE);
mSchemeBasicPaint.setColor(calendar.getSchemeColor());
//绘制圆圈
canvas.drawCircle(x + mItemWidth - mPadding - mRadio / 2, y + mPadding + mRadio, mRadio, mSchemeBasicPaint);
//绘制事件文本
canvas.drawText(calendar.getScheme(), x + mItemWidth - mPadding - mRadio, y + mPadding + mSchemeBaseLine, mTextPaint); } else {
canvas.drawText(String.valueOf(calendar.getDay()), cx, mTextBaseLine + top,
calendar.isCurrentDay() ? mCurDayTextPaint :
calendar.isCurrentMonth() ? mCurMonthTextPaint : mOtherMonthTextPaint);
canvas.drawText(calendar.getLunar(), cx, mTextBaseLine + y + mItemHeight / 10, mCurMonthLunarTextPaint);
}
} /**
* dp转px
*
* @param context context
* @param dpValue dp
* @return px
*/
private static int dipToPx(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
}

第二步:使用方法、app:calendar_card_view="xxx.xx.MeiZuCalendarCardView"

魅族风格日历效果预览

Android开源的精美日历控件,热插拔设计的万能自定义UI                    Android开源的精美日历控件,热插拔设计的万能自定义UI

快速年月份选择

Android开源的精美日历控件,热插拔设计的万能自定义UI

其它作者实现的几个UI效果预览,简单源码都在demo可以看到

多彩风格界面

Android开源的精美日历控件,热插拔设计的万能自定义UI                    Android开源的精美日历控件,热插拔设计的万能自定义UI

下标风格界面

Android开源的精美日历控件,热插拔设计的万能自定义UI                    Android开源的精美日历控件,热插拔设计的万能自定义UI

简单没有农历界面

Android开源的精美日历控件,热插拔设计的万能自定义UI                    Android开源的精美日历控件,热插拔设计的万能自定义UI

更多参考用法移步APP Demo,里面作者实现了几种类型的风格,可以参考实现

项目开源地址

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

如果觉得源码可以请给个star,源码注释完善,简单易懂,容易学习。

Android开源的精美日历控件,热插拔设计的万能自定义UI的更多相关文章

  1. iOS 简单易用的二维码扫描及生成二维码三方控件LFQRCode,可灵活自定义UI

    一.扫码 扫描的控件是一个view,使用者只需贴在自己的控制器内即可.其他UI用户可在自己控制器随便添加.代码如下 - (void)viewDidLoad { [super viewDidLoad]; ...

  2. Android超炫日期日历控件:TimesSquare

    先看效果图: 使用说明: 在布局文件里: <com.squareup.timessquare.CalendarPickerView android:id="@+id/calendar_ ...

  3. Android精美的日历控件

    网上看到的精美日历控件,谨以此文记录一下,用到的时候再来翻翻 源码地址 : http://download.csdn.net/detail/abc13939746593/7265459

  4. Android自己定义组件之日历控件-精美日历实现(内容、样式可扩展)

    需求 我们知道.Android系统本身有自带的日历控件,网络上也有非常多开源的日历控件资源.可是这些日历控件往往样式较单一.API较多.不易于在实际项目中扩展并实现出符合详细样式风格的,内容可定制的效 ...

  5. Android自定义View(CustomCalendar-定制日历控件)

    转载请标明出处: http://blog.csdn.net/xmxkf/article/details/54020386 本文出自:[openXu的博客] 目录: 1分析 2自定义属性 3onMeas ...

  6. Android 开源组件 ----- Android LoopView无限自动轮转控件

    Android 开源组件 ----- Android LoopView无限自动轮转控件 2015-12-28 15:26 by 杰瑞教育, 32 阅读, 0 评论, 收藏, 编辑 一.组件介绍 App ...

  7. android 自定义日历控件

    日历控件View: /** * 日历控件 功能:获得点选的日期区间 * */ public class CalendarView extends View implements View.OnTouc ...

  8. Android开发之日历控件实现

    Android开发之日历控件实现:以下都是转载的. 日历控件 日历控件 日历控件 日历控件

  9. android日历控件&lpar;一&rpar;

    自定义日历并且具备设置今天以前的时间不可点选,以前的颜色和当前的颜色不同,以及获取两次点击日期之间间隔的天数所以说细节比较多 个人习惯,先上图 靠,笔记本不知道怎么回事,禁用到触摸板之后 再次唤醒屏幕 ...

随机推荐

  1. &lbrack;转&rsqb;使用 HTML5 IndexedDB API

    本地数据持久性提高了 Web 应用程序可访问性和移动应用程序响应能力 索引数据库 (IndexedDB) API(作为 HTML5 的一部分)对创建具有丰富本地存储数据的数据密集型的离线 HTML5 ...

  2. ORACLE RAC集群硬件资源管理与单节点的区别

    硬件资源是由OS kernel管理的,应用软件是不能直接访问硬件的,必须通过OS kernel提供的API接口间接访问,OS kernel 除了要完成用户的请求,还通过进程调度等机制来控制多进程对资源 ...

  3. printf参数的问题

    根据前面的某一篇的文章,可以清楚的看到:对于每一个函数,通过这个函数的[ebp+x]就可以直接访问到它调用的时候传进来的形参的值,通过[ebp-x]就可以直接访问它的局部变量. 所以printf这个函 ...

  4. 认识Java(1)

    Java是一门程序设计语言. 有三个方向: JAVA SE (java platform standard edition):包含java核心类,如数据库.接口.网络编程. JAVA ME(java ...

  5. 彻底卸载Oracle database 12c教程

    1.WIN+R,然后输入regedit,回车:2.在注册表中,进入目录:\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services,删除所有以oracl ...

  6. SDN架构

    一:网络设备(Network Devices) 二:南向接口(Southbound Interface) 三:控制器(Controllers) 四:北向接口(Northbound Interface) ...

  7. 在Ubuntu 16&period;04 安装python3&period;6 环境并设置为默认

    在Ubuntu 16.04 安装python3.6 环境并设置为默认 1.添加python3.6安装包,并且安装 sudo apt-get install software-properties-co ...

  8. Automate Screen or Button Taps via Tasker &colon; Simulating keypress events

    When using Tasker, sometimes we want to do some automation on screen e.g. screen or button taps. At ...

  9. docker-8-本地镜像发布到阿里云

    镜像的生成方法 1.前面的DockerFile   2.从容器创建一个新的镜像 docker commit [OPTIONS] 容器ID [REPOSITORY[:TAG]] 将本地镜像推送到阿里云 ...

  10. webview中播放视屏,返回或者退出后,仍然会有声音。

    解决办法: protected void onPause() { super.onPause(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODE ...