摘要:日歷的項目地址示例上的一個日歷控件,可以定制成自己想要的樣子。跳轉到指定日期,默認支持動畫切換自定義日歷,支持組合的方式和利用繪制的方式自定義頂部的可以給添加自定義的額外數據,實現各種額外的功能。
介紹最近自己寫了個demo,用到了日歷方面的東西,然后實現來一下,最后打算封裝一下,以后可以直接拿來使用。
參考了Android的一個開源日歷庫github.com/huanghaibin…,實現思路其實差不多,都是可以利用canvas將日歷給畫出來。
Flutter日歷的項目地址:github.com/LXD31256949…
示例Flutter上的一個日歷控件,可以定制成自己想要的樣子。
主要功能
支持公歷,農歷,節氣,傳統節日,常用節假日
日期范圍設置,默認支持的最大日期范圍為1971.01-2055.12
禁用日期范圍設置,比如想實現某范圍的日期內可以點擊,范圍外的日期置灰
支持單選、多選模式,提供多選超過限制個數的回調和多選超過指定范圍的回調。
跳轉到指定日期,默認支持動畫切換
自定義日歷Item,支持組合widget的方式和利用canvas繪制的方式
自定義頂部的WeekBar
可以給Item添加自定義的額外數據,實現各種額外的功能。比如實現進度條風格的日歷
使用在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來配置一些數據,并且可以通過CalendarController進行一些操作或者事件監聽,比如滾動到下一個月,獲取當前被選中的Item等等。
下面是CalendarController中一些支持自定義配置的屬性。不配置的話,會有對應的默認值。
//默認是單選,可以配置為MODE_SINGLE_SELECT,MODE_MULTI_SELECT int selectMode; //日歷顯示的最小年份和最大年份 int minYear; int maxYear; //日歷顯示的最小年份的月份,最大年份的月份 int minYearMonth; int maxYearMonth; //日歷顯示的當前的年份和月份 int nowYear; int nowMonth; //可操作的范圍設置,比如點擊選擇 int minSelectYear; int minSelectMonth; int minSelectDay; int maxSelectYear; int maxSelectMonth; int maxSelectDay; //注意:不能超過對應月份的總天數 Set利用controller添加監聽事件selectedDateList = new Set(); //被選中的日期,用于多選 DateModel selectDateModel; //當前選擇項,用于單選 int maxMultiSelectCount; //多選,最多選多少個 Map extraDataMap = new Map(); //自定義額外的數據 //各種事件回調 OnMonthChange monthChange; //月份切換事件 OnCalendarSelect calendarSelect; //點擊選擇事件 OnMultiSelectOutOfRange multiSelectOutOfRange; //多選超出指定范圍 OnMultiSelectOutOfSize multiSelectOutOfSize; //多選超出限制個數 //支持自定義繪制 DayWidgetBuilder dayWidgetBuilder; //創建日歷item WeekBarItemWidgetBuilder weekBarItemWidgetBuilder; //創建頂部的weekbar //構造函數 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})
比如月份切換事件、點擊選擇事件。
//月份切換監聽 void addMonthChangeListener(OnMonthChange listener) { this.monthChange = listener; } //點擊選擇監聽 void addOnCalendarSelectListener(OnCalendarSelect listener) { this.calendarSelect = listener; } //多選超出指定范圍 void addOnMultiSelectOutOfRangeListener(OnMultiSelectOutOfRange listener) { this.multiSelectOutOfRange = listener; } //多選超出限制個數 void addOnMultiSelectOutOfSizeListener(OnMultiSelectOutOfSize listener) { this.multiSelectOutOfSize = listener; }利用controller來控制日歷的切換,支持配置動畫
//跳轉到指定日期
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來獲取日歷的一些數據信息
// 獲取當前的月份 DateTime getCurrentMonth(); //獲取被選中的日期,多選 Set自定義UIgetMultiSelectCalendar(); //獲取被選中的日期,單選 DateModel getSingleSelectCalendar();
包括自定義WeekBar、自定義日歷Item,默認使用的都是DefaultXXXWidget。
只要繼承對應的Base類,實現相應的方法,然后只需要在配置Controller的時候,實現相應的Builder方法就可以了。
//支持自定義繪制 DayWidgetBuilder dayWidgetBuilder; //創建日歷item WeekBarItemWidgetBuilder weekBarItemWidgetBuilder; //創建頂部的weekbar自定義WeekBar
繼承BaseWeekBar,重寫getWeekBarItem(index)方法就可以。隨便你怎么實現,只需要返回一個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的方式來創建,一種是利用Canvas來自定義繪制Item。最后只需要在CalendarController的構造參數中進行配置就可以了。
繼承BaseCombineDayWidget,重寫getNormalWidget(DateModel dateModel) 和getSelectedWidget(DateModel dateModel)就可以了,返回對應的widget就行。
class DefaultCombineDayWidget extends BaseCombineDayWidget { DefaultCombineDayWidget(DateModel dateModel) : super(dateModel); @override Widget getNormalWidget(DateModel dateModel) { //實現默認狀態下的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) { //實現默認狀態下的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; //農歷字符串
String solarTerm; //24節氣
String gregorianFestival; //公歷節日
String traditionFestival; //傳統農歷節日
bool isCurrentDay; //是否是今天
bool isLeapYear; //是否是閏年
bool isWeekend; //是否是周末
int leapMonth; //是否是閏月
Object extraData; //自定義的額外數據
bool isInRange = false; //是否在范圍內,比如可以實現在某個范圍外,設置置灰的功能
bool isSelected; //是否被選中,用來實現一些標記或者選擇功能
@override
String toString() {
return "DateModel{year: $year, month: $month, day: $day}";
} //如果是閏月,則返回閏月
//轉化成DateTime格式
DateTime getDateTime() {
return new DateTime(year, month, day);
}
//根據DateTime創建對應的model,并初始化農歷和傳統節日等信息
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
優化代碼實現
支持屏蔽指定的某些天
繼續寫幾個不同風格的Demo
支持周視圖
支持動畫切換周視圖和月視圖
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/6883.html
摘要:注釋處的方法是程序的入口,使用了符號,這是中單行函數或方法的簡寫,等價于如下代碼方法是框架的入口,如果不返回方法,那么執行的是一個控制臺應用。 本文首發于微信公眾號「劉望舒」 前言 最近的Google I/O大會上,Flutter1.5 開始支持移動、Web、桌面和嵌入式設備,從不溫不火的sky一直進化到如今熱門的Flutter,Flutter的發展已經超出很多人的想象。我對跨平臺技術一...
摘要:意味著屬性必須在構造函數中就被初始化完成,不接受提前定義,也不接受更改。所以,在生命周期中動態的改變對象的屬性是不可能的,必須使用框架的方法來為構造函數動態指定參數,從而達到改變組件屬性的功能。 本文適合使用Flutter開發過一段時間的開發者閱讀,旨在分享一種避免Flutter的UI代碼嵌套太深問題的方法。如果對本文內容或觀點有相關疑問,歡迎在評論中指出。 優化效果(縮略圖): sh...
摘要:本文將以一個簡單的為例,介紹下相關原理及定制與優化。模式對應了的模式,又稱檢查模式或者慢速模式。為快速啟動,快速執行,包大小做了優化。并不支持模擬器的原因在于,模擬器上的診斷并不代表真實的性能。因此本文主要討論因引入的構建,運行等原理。 摘要: 閑魚技術-正物 問題背景 對于開發者而言,什么是Flutter?它是用什么語言編寫的,包含哪幾部分,是如何被編譯,運行到設備上的呢?Flutt...
閱讀 1094·2021-09-22 15:19
閱讀 1710·2021-08-23 09:46
閱讀 2233·2021-08-09 13:47
閱讀 1412·2019-08-30 15:55
閱讀 1420·2019-08-30 15:55
閱讀 1980·2019-08-30 15:54
閱讀 2804·2019-08-30 15:53
閱讀 718·2019-08-30 11:03