摘要:日歷的項目地址示例上的一個日歷控件,可以定制成自己想要的樣子。跳轉(zhuǎn)到指定日期,默認(rèn)支持動畫切換自定義日歷,支持組合的方式和利用繪制的方式自定義頂部的可以給添加自定義的額外數(shù)據(jù),實現(xiàn)各種額外的功能。
介紹最近自己寫了個demo,用到了日歷方面的東西,然后實現(xiàn)來一下,最后打算封裝一下,以后可以直接拿來使用。
參考了Android的一個開源日歷庫github.com/huanghaibin…,實現(xiàn)思路其實差不多,都是可以利用canvas將日歷給畫出來。
Flutter日歷的項目地址:github.com/LXD31256949…
示例Flutter上的一個日歷控件,可以定制成自己想要的樣子。
主要功能
支持公歷,農(nóng)歷,節(jié)氣,傳統(tǒng)節(jié)日,常用節(jié)假日
日期范圍設(shè)置,默認(rèn)支持的最大日期范圍為1971.01-2055.12
禁用日期范圍設(shè)置,比如想實現(xiàn)某范圍的日期內(nèi)可以點擊,范圍外的日期置灰
支持單選、多選模式,提供多選超過限制個數(shù)的回調(diào)和多選超過指定范圍的回調(diào)。
跳轉(zhuǎn)到指定日期,默認(rèn)支持動畫切換
自定義日歷Item,支持組合widget的方式和利用canvas繪制的方式
自定義頂部的WeekBar
可以給Item添加自定義的額外數(shù)據(jù),實現(xiàn)各種額外的功能。比如實現(xiàn)進(jìn)度條風(fēng)格的日歷
使用在pubspec.yaml添加依賴:
flutter_custom_calendar: git: url: https://github.com/LXD312569496/flutter_custom_calendar.git
引入flutter_custom_calendar,就可以使用CalendarViewWidget,配置CalendarController就可以了。
import "package:flutter_custom_calendar/flutter_custom_calendar.dart";
CalendarViewWidget({@required this.calendarController, this.boxDecoration});
boxDecoration用來配置整體的背景
利用CalendarController來配置一些數(shù)據(jù),并且可以通過CalendarController進(jìn)行一些操作或者事件監(jiān)聽,比如滾動到下一個月,獲取當(dāng)前被選中的Item等等。
下面是CalendarController中一些支持自定義配置的屬性。不配置的話,會有對應(yīng)的默認(rèn)值。
//默認(rèn)是單選,可以配置為MODE_SINGLE_SELECT,MODE_MULTI_SELECT int selectMode; //日歷顯示的最小年份和最大年份 int minYear; int maxYear; //日歷顯示的最小年份的月份,最大年份的月份 int minYearMonth; int maxYearMonth; //日歷顯示的當(dāng)前的年份和月份 int nowYear; int nowMonth; //可操作的范圍設(shè)置,比如點擊選擇 int minSelectYear; int minSelectMonth; int minSelectDay; int maxSelectYear; int maxSelectMonth; int maxSelectDay; //注意:不能超過對應(yīng)月份的總天數(shù) Set利用controller添加監(jiān)聽事件selectedDateList = new Set(); //被選中的日期,用于多選 DateModel selectDateModel; //當(dāng)前選擇項,用于單選 int maxMultiSelectCount; //多選,最多選多少個 Map extraDataMap = new Map(); //自定義額外的數(shù)據(jù) //各種事件回調(diào) OnMonthChange monthChange; //月份切換事件 OnCalendarSelect calendarSelect; //點擊選擇事件 OnMultiSelectOutOfRange multiSelectOutOfRange; //多選超出指定范圍 OnMultiSelectOutOfSize multiSelectOutOfSize; //多選超出限制個數(shù) //支持自定義繪制 DayWidgetBuilder dayWidgetBuilder; //創(chuàng)建日歷item WeekBarItemWidgetBuilder weekBarItemWidgetBuilder; //創(chuàng)建頂部的weekbar //構(gòu)造函數(shù) CalendarController( {int selectMode = Constants.MODE_SINGLE_SELECT, DayWidgetBuilder dayWidgetBuilder = defaultCustomDayWidget, WeekBarItemWidgetBuilder weekBarItemWidgetBuilder = defaultWeekBarWidget, int minYear = 1971, int maxYear = 2055, int minYearMonth = 1, int maxYearMonth = 12, int nowYear = -1, int nowMonth = -1, int minSelectYear = 1971, int minSelectMonth = 1, int minSelectDay = 1, int maxSelectYear = 2055, int maxSelectMonth = 12, int maxSelectDay = 30, Set selectedDateTimeList = EMPTY_SET, DateModel selectDateModel, int maxMultiSelectCount = 9999, Map extraDataMap = EMPTY_MAP})
比如月份切換事件、點擊選擇事件。
//月份切換監(jiān)聽 void addMonthChangeListener(OnMonthChange listener) { this.monthChange = listener; } //點擊選擇監(jiān)聽 void addOnCalendarSelectListener(OnCalendarSelect listener) { this.calendarSelect = listener; } //多選超出指定范圍 void addOnMultiSelectOutOfRangeListener(OnMultiSelectOutOfRange listener) { this.multiSelectOutOfRange = listener; } //多選超出限制個數(shù) void addOnMultiSelectOutOfSizeListener(OnMultiSelectOutOfSize listener) { this.multiSelectOutOfSize = listener; }利用controller來控制日歷的切換,支持配置動畫
//跳轉(zhuǎn)到指定日期
void moveToCalendar(int year, int month, int day,
{bool needAnimation = false,
Duration duration = const Duration(milliseconds: 500),
Curve curve = Curves.ease});
//切換到下一年
void moveToNextYear();
//切換到上一年
void moveToPreviousYear();
//切換到下一個月份,
void moveToNextMonth();
//切換到上一個月份
void moveToPreviousMonth();
利用controller來獲取日歷的一些數(shù)據(jù)信息
// 獲取當(dāng)前的月份 DateTime getCurrentMonth(); //獲取被選中的日期,多選 Set自定義UIgetMultiSelectCalendar(); //獲取被選中的日期,單選 DateModel getSingleSelectCalendar();
包括自定義WeekBar、自定義日歷Item,默認(rèn)使用的都是DefaultXXXWidget。
只要繼承對應(yīng)的Base類,實現(xiàn)相應(yīng)的方法,然后只需要在配置Controller的時候,實現(xiàn)相應(yīng)的Builder方法就可以了。
//支持自定義繪制 DayWidgetBuilder dayWidgetBuilder; //創(chuàng)建日歷item WeekBarItemWidgetBuilder weekBarItemWidgetBuilder; //創(chuàng)建頂部的weekbar自定義WeekBar
繼承BaseWeekBar,重寫getWeekBarItem(index)方法就可以。隨便你怎么實現(xiàn),只需要返回一個Widget就可以了。
class DefaultWeekBar extends BaseWeekBar {
const DefaultWeekBar({Key key}) : super(key: key);
@override
Widget getWeekBarItem(int index) {
/**
* 自定義Widget
*/
return new Container(
height: 40,
alignment: Alignment.center,
child: new Text(
Constants.WEEK_LIST[index],
style: topWeekTextStyle,
),
);
}
}
自定義日歷Item:
提供兩種方法,一種是利用組合widget的方式來創(chuàng)建,一種是利用Canvas來自定義繪制Item。最后只需要在CalendarController的構(gòu)造參數(shù)中進(jìn)行配置就可以了。
繼承BaseCombineDayWidget,重寫getNormalWidget(DateModel dateModel) 和getSelectedWidget(DateModel dateModel)就可以了,返回對應(yīng)的widget就行。
class DefaultCombineDayWidget extends BaseCombineDayWidget { DefaultCombineDayWidget(DateModel dateModel) : super(dateModel); @override Widget getNormalWidget(DateModel dateModel) { //實現(xiàn)默認(rèn)狀態(tài)下的UI } @override Widget getSelectedWidget(DateModel dateModel) { //繪制被選中的UI } }
繼承BaseCustomDayWidget,重寫drawNormal和drawSelected的兩個方法就可以了,利用canvas自己繪制Item。
class DefaultCustomDayWidget extends BaseCustomDayWidget { DefaultCustomDayWidget(DateModel dateModel) : super(dateModel); @override void drawNormal(DateModel dateModel, Canvas canvas, Size size) { //實現(xiàn)默認(rèn)狀態(tài)下的UI defaultDrawNormal(dateModel, canvas, size); } @override void drawSelected(DateModel dateModel, Canvas canvas, Size size) { //繪制被選中的UI defaultDrawSelected(dateModel, canvas, size); } }DateModel實體類
日歷所用的日期的實體類DateModel,有下面這些屬性。
/**
* 日期的實體類
*/
class DateModel {
int year;
int month;
int day = 1;
int lunarYear;
int lunarMonth;
int lunarDay;
String lunarString; //農(nóng)歷字符串
String solarTerm; //24節(jié)氣
String gregorianFestival; //公歷節(jié)日
String traditionFestival; //傳統(tǒng)農(nóng)歷節(jié)日
bool isCurrentDay; //是否是今天
bool isLeapYear; //是否是閏年
bool isWeekend; //是否是周末
int leapMonth; //是否是閏月
Object extraData; //自定義的額外數(shù)據(jù)
bool isInRange = false; //是否在范圍內(nèi),比如可以實現(xiàn)在某個范圍外,設(shè)置置灰的功能
bool isSelected; //是否被選中,用來實現(xiàn)一些標(biāo)記或者選擇功能
@override
String toString() {
return "DateModel{year: $year, month: $month, day: $day}";
} //如果是閏月,則返回閏月
//轉(zhuǎn)化成DateTime格式
DateTime getDateTime() {
return new DateTime(year, month, day);
}
//根據(jù)DateTime創(chuàng)建對應(yīng)的model,并初始化農(nóng)歷和傳統(tǒng)節(jié)日等信息
static DateModel fromDateTime(DateTime dateTime) {
DateModel dateModel = new DateModel()
..year = dateTime.year
..month = dateTime.month
..day = dateTime.day;
LunarUtil.setupLunarCalendar(dateModel);
return dateModel;
}
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is DateModel &&
runtimeType == other.runtimeType &&
year == other.year &&
month == other.month &&
day == other.day;
@override
int get hashCode => year.hashCode ^ month.hashCode ^ day.hashCode;
}
TODO LIST
優(yōu)化代碼實現(xiàn)
支持屏蔽指定的某些天
繼續(xù)寫幾個不同風(fēng)格的Demo
支持周視圖
支持動畫切換周視圖和月視圖
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/6883.html
摘要:注釋處的方法是程序的入口,使用了符號,這是中單行函數(shù)或方法的簡寫,等價于如下代碼方法是框架的入口,如果不返回方法,那么執(zhí)行的是一個控制臺應(yīng)用。 本文首發(fā)于微信公眾號「劉望舒」 前言 最近的Google I/O大會上,F(xiàn)lutter1.5 開始支持移動、Web、桌面和嵌入式設(shè)備,從不溫不火的sky一直進(jìn)化到如今熱門的Flutter,F(xiàn)lutter的發(fā)展已經(jīng)超出很多人的想象。我對跨平臺技術(shù)一...
摘要:意味著屬性必須在構(gòu)造函數(shù)中就被初始化完成,不接受提前定義,也不接受更改。所以,在生命周期中動態(tài)的改變對象的屬性是不可能的,必須使用框架的方法來為構(gòu)造函數(shù)動態(tài)指定參數(shù),從而達(dá)到改變組件屬性的功能。 本文適合使用Flutter開發(fā)過一段時間的開發(fā)者閱讀,旨在分享一種避免Flutter的UI代碼嵌套太深問題的方法。如果對本文內(nèi)容或觀點有相關(guān)疑問,歡迎在評論中指出。 優(yōu)化效果(縮略圖): sh...
摘要:本文將以一個簡單的為例,介紹下相關(guān)原理及定制與優(yōu)化。模式對應(yīng)了的模式,又稱檢查模式或者慢速模式。為快速啟動,快速執(zhí)行,包大小做了優(yōu)化。并不支持模擬器的原因在于,模擬器上的診斷并不代表真實的性能。因此本文主要討論因引入的構(gòu)建,運行等原理。 摘要: 閑魚技術(shù)-正物 問題背景 對于開發(fā)者而言,什么是Flutter?它是用什么語言編寫的,包含哪幾部分,是如何被編譯,運行到設(shè)備上的呢?Flutt...
閱讀 1083·2021-09-22 15:19
閱讀 1697·2021-08-23 09:46
閱讀 2226·2021-08-09 13:47
閱讀 1405·2019-08-30 15:55
閱讀 1408·2019-08-30 15:55
閱讀 1974·2019-08-30 15:54
閱讀 2795·2019-08-30 15:53
閱讀 713·2019-08-30 11:03