推薦一款優雅的日歷控件
原文鏈接:https://mp.weixin.qq.com/s/SmxDiWIidHS2hwVvFcz_hw
項目需要用到日歷控件,這是我們的效果圖。
去github上搜了一哈,搜到大神寫的CalendarView
,各種炫酷效果,我這種的也只需要自定義效果就可以了,話不多說,直接開擼!
這裏附上github的鏈接地址:https://github.com/huanghaibin-dev/CalendarView, 裏面的api文檔說明還是很齊全的,這裏就直接記錄我的開發歷程。
gradle 關聯
implementation ‘com.haibin:calendarview:3.4.0‘
使用
剛開始布局中使用的話註意是 <com.haibin.calendarview.CalendarView />
<CalendarView />
使用的是系統自帶的日歷控件。
<com.haibin.calendarview.CalendarView
android:layout_width="match_parent"
android:layout_height="wrap_content" />
可以直接預覽效果,一些屬性配置項:
app:month_view_show_mode="mode_fix"
配置月視圖的顯示模式
app:current_month_text_color="#212121"
當前頁月份的月字體顏色
app:other_month_text_color="#cccccc"
等等一系列的屬性配置,文檔裏都是有的。當然要實現自己的效果,那些屬性是不夠的,需要我們自定義MonthView 去實現(項目地址裏也有demo可下載參考)。
自定義 MonthView
自定義MyMonthView
類繼承自 MonthView
,xml布局裏添加屬性 app:month_view="com.calendar.MyMonthView"
,這裏的路徑是自己實際項目中的monthView的路徑,需要我們自己去繪制日歷。
//取消日歷字體加粗 mCurMonthTextPaint.setFakeBoldText(false); mOtherMonthTextPaint.setFakeBoldText(false);
這裏插個題外的知識點tip: setFakeBoldText(true)
的加粗效果比 android:textStyle="bold"
屬性的加粗效果要弱點,就是不會太粗,又比細稍微粗一點的效果~ 了解一下
在onDrawText
裏進行繪制,正常樣式的日歷可正常顯示時間的
@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;
int cy = y + mItemHeight / 2;
canvas.drawText(String.valueOf(calendar.getDay()), cx, baselineY, calendar.isCurrentMonth() ? mCurMonthTextPaint : mOtherMonthTextPaint);
}
這裏要分類下我們需要幾種類型的樣式:
1、不可完成的
2、可以完成的
3、今日已完成的
4、歷史已完成的
模擬數據,通過scheme 標記區分各樣式
Calendar calendar1 = getSchemeCalendar(2018, 8, 11, "1");
Calendar calendar2 = getSchemeCalendar(2018, 8, 12, "2");
Calendar calendar3 = getSchemeCalendar(2018, 8, 13, "3");
Calendar calendar4 = getSchemeCalendar(2018, 8, 6, "4");
map.put(calendar1.toString(), calendar1);
map.put(calendar2.toString(), calendar2);
map.put(calendar3.toString(), calendar3);
map.put(calendar4.toString(), calendar4);
calendarView.setSchemeDate(map);
private Calendar getSchemeCalendar(int year, int month, int day, String text) {
Calendar calendar = new Calendar();
calendar.setYear(year);
calendar.setMonth(month);
calendar.setDay(day);
calendar.setScheme(text);
return calendar;
}
初始化兩個paint,有兩張圖片資源的用Bitmap去繪制
paint1.setColor(ContextCompat.getColor(context, R.color.green));
paint1.setTextSize(DensityUtil.spToPx(context, 13));
paint1.setStyle(Paint.Style.STROKE);
paint1.setAntiAlias(true);
paint1.setTextAlign(Paint.Align.CENTER);
paint2.setColor(ContextCompat.getColor(context, R.color.white));
paint2.setTextSize(DensityUtil.spToPx(context, 13));
paint2.setAntiAlias(true);
paint2.setTextAlign(Paint.Align.CENTER);
dayBgBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.day_bg);
daySuccessBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.day_success);
主要的方法 onDrawText ,根據不同scheme 繪制各view
@Override
protected void onDrawText(Canvas canvas, Calendar calendar, int x, int y, boolean hasScheme, boolean isSelected) {
//這裏的x、y 是每日的起點坐標
float baselineY = mTextBaseLine + y;
int cx = x + mItemWidth / 2;
int cy = y + mItemHeight / 2;
if ("1".equals(calendar.getScheme())) {
// 不可完成的,繪制圓
paint1.setStrokeWidth(0);
canvas.drawText(String.valueOf(calendar.getDay()), cx, baselineY, paint1);
paint1.setStrokeWidth(DensityUtil.dpToPx(context, 1));
canvas.drawCircle(cx, cy + 3, mItemWidth / 4 - 9, paint1);
} else if ("2".equals(calendar.getScheme())) {
//可以完成的,繪制背景圖
canvas.drawText(String.valueOf(calendar.getDay()), cx, baselineY, paint2);
canvas.drawBitmap(dayBgBitmap, x + mItemWidth / 4 - 5, y + mItemHeight / 4 + 8, paint2);
} else if ("3".equals(calendar.getScheme())) {
//今日已完成的,繪制圓+打勾圖片
paint1.setStrokeWidth(0);
canvas.drawText(String.valueOf(calendar.getDay()), cx, baselineY, paint1);
paint1.setStrokeWidth(DensityUtil.dpToPx(context, 1));
canvas.drawCircle(cx, cy + 3, mItemWidth / 4 - 9, paint1);
canvas.drawBitmap(daySuccessBitmap, x + mItemWidth * 3 / 4 - 18, y + mItemHeight * 3 / 4 - 24, paint1);
} else if ("4".equals(calendar.getScheme())) {
//歷史已完成的,繪制打勾圖片
paint1.setStrokeWidth(0);
canvas.drawText(String.valueOf(calendar.getDay()), cx, baselineY, paint1);
canvas.drawBitmap(daySuccessBitmap, x + mItemWidth * 3 / 4 - 18, y + mItemHeight * 3 / 4 - 40, paint1);
} else {
//正常日期的顯示
canvas.drawText(String.valueOf(calendar.getDay()), cx, baselineY, calendar.isCurrentMonth() ? mCurMonthTextPaint : mOtherMonthTextPaint);
}
}
至此,視圖繪制完成。
接下來完成基本的api調用。
api 調用
初始化賦值當前的年月,日歷切換時,時間對應改變。
//初始化當前年月
tvMonth.setText(calendarView.getCurYear() + "年" + calendarView.getCurMonth() + "月");
//月份切換改變事件
calendarView.setOnMonthChangeListener(new CalendarView.OnMonthChangeListener() {
@Override
public void onMonthChange(int year, int month) {
tvMonth.setText(year + "年" + month + "月");
}
});
布局裏有個時間選擇器,用於選擇年月的,這裏采用的是 Android-PickerView 時間選擇器。
//時間選擇器選擇年月,對應的日歷切換到指定日期
picker.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
TimePickerView pvTime = new TimePickerBuilder(MainActivity.this, new OnTimeSelectListener() {
@Override
public void onTimeSelect(Date date, View v) {
java.util.Calendar c = java.util.Calendar.getInstance();
c.setTime(date);
int year = c.get(java.util.Calendar.YEAR);
int month = c.get(java.util.Calendar.MONTH);
//滾動到指定日期
calendarView.scrollToCalendar(year, month + 1, 1);
}
}).setType(type).build();
pvTime.show();
}
});
日期的選擇監聽事件
calendarView.setOnDateSelectedListener(new CalendarView.OnDateSelectedListener() {
@Override
public void onDateSelected(Calendar calendar, boolean isClick) {
}
});
效果完成圖,當然不同項目裏的效果圖是不一樣的,只要會canvas的基本繪制都是可以達到各自想要的效果的。
詳細代碼見
github地址:https://github.com/taixiang/calendar
歡迎關註我的博客:https://blog.manjiexiang.cn/
更多精彩歡迎關註微信號:春風十裏不如認識你
有個「佛系碼農圈」,歡迎大家加入暢聊,開心就好!
過期了,可加我微信 tx467220125 拉你入群。
推薦一款優雅的日歷控件