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

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

听说第一页无效果图就看不下去了?先上个高仿魅族日历界面

47bbfbafc9ff

魅族界面.png

47bbfbafc9ff

魅族收缩.png

项目开源地址

CalendarView的优势:

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

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

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

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

先看看控件的attr

XML用法

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

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical"

android:background="#fff"

app:calendar_content_view_id="@+id/linearView">

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" />

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"/>

熟悉一下这几个简单的特性,看看日历内容界面的绘制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"

效果预览

高仿魅族日历界面

47bbfbafc9ff

魅族界面.png

47bbfbafc9ff

魅族收缩.png

快速年月份选择

47bbfbafc9ff

月份界面.png

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

多彩风格界面

47bbfbafc9ff

多彩界面.png

47bbfbafc9ff

多彩收缩.png

下标风格界面

47bbfbafc9ff

下标界面.png

47bbfbafc9ff

下标收缩.png

简单没有农历界面

47bbfbafc9ff

简单界面.png

47bbfbafc9ff

简单收缩.png

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

项目开源地址

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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值