成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

Flutter日歷,可以自定義風(fēng)格UI

icyfire / 3354人閱讀

摘要:日歷的項(xiàng)目地址示例上的一個(gè)日歷控件,可以定制成自己想要的樣子。跳轉(zhuǎn)到指定日期,默認(rèn)支持動(dòng)畫(huà)切換自定義日歷,支持組合的方式和利用繪制的方式自定義頂部的可以給添加自定義的額外數(shù)據(jù),實(shí)現(xiàn)各種額外的功能。

介紹

最近自己寫(xiě)了個(gè)demo,用到了日歷方面的東西,然后實(shí)現(xiàn)來(lái)一下,最后打算封裝一下,以后可以直接拿來(lái)使用。

參考了Android的一個(gè)開(kāi)源日歷庫(kù)github.com/huanghaibin…,實(shí)現(xiàn)思路其實(shí)差不多,都是可以利用canvas將日歷給畫(huà)出來(lái)。

Flutter日歷的項(xiàng)目地址:github.com/LXD31256949…

示例

Flutter上的一個(gè)日歷控件,可以定制成自己想要的樣子。

主要功能

支持公歷,農(nóng)歷,節(jié)氣,傳統(tǒng)節(jié)日,常用節(jié)假日

日期范圍設(shè)置,默認(rèn)支持的最大日期范圍為1971.01-2055.12

禁用日期范圍設(shè)置,比如想實(shí)現(xiàn)某范圍的日期內(nèi)可以點(diǎn)擊,范圍外的日期置灰

支持單選、多選模式,提供多選超過(guò)限制個(gè)數(shù)的回調(diào)和多選超過(guò)指定范圍的回調(diào)。

跳轉(zhuǎn)到指定日期,默認(rèn)支持動(dòng)畫(huà)切換

自定義日歷Item,支持組合widget的方式和利用canvas繪制的方式

自定義頂部的WeekBar

可以給Item添加自定義的額外數(shù)據(jù),實(shí)現(xiàn)各種額外的功能。比如實(shí)現(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用來(lái)配置整體的背景

利用CalendarController來(lái)配置一些數(shù)據(jù),并且可以通過(guò)CalendarController進(jìn)行一些操作或者事件監(jiān)聽(tīng),比如滾動(dòng)到下一個(gè)月,獲取當(dāng)前被選中的Item等等。

下面是CalendarController中一些支持自定義配置的屬性。不配置的話,會(huì)有對(duì)應(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è)置,比如點(diǎn)擊選擇
int minSelectYear;
int minSelectMonth;
int minSelectDay;

int maxSelectYear;
int maxSelectMonth;
int maxSelectDay; //注意:不能超過(guò)對(duì)應(yīng)月份的總天數(shù)

Set selectedDateList = new Set(); //被選中的日期,用于多選
DateModel selectDateModel; //當(dāng)前選擇項(xiàng),用于單選
int maxMultiSelectCount; //多選,最多選多少個(gè)
Map extraDataMap = new Map(); //自定義額外的數(shù)據(jù)

//各種事件回調(diào)
OnMonthChange monthChange; //月份切換事件
OnCalendarSelect calendarSelect; //點(diǎn)擊選擇事件
OnMultiSelectOutOfRange multiSelectOutOfRange; //多選超出指定范圍
OnMultiSelectOutOfSize multiSelectOutOfSize; //多選超出限制個(gè)數(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})

利用controller添加監(jiān)聽(tīng)事件

比如月份切換事件、點(diǎn)擊選擇事件。

//月份切換監(jiān)聽(tīng)
void addMonthChangeListener(OnMonthChange listener) {
  this.monthChange = listener;
}
//點(diǎn)擊選擇監(jiān)聽(tīng)
void addOnCalendarSelectListener(OnCalendarSelect listener) {
  this.calendarSelect = listener;
}
//多選超出指定范圍
void addOnMultiSelectOutOfRangeListener(OnMultiSelectOutOfRange listener) {
  this.multiSelectOutOfRange = listener;
}
//多選超出限制個(gè)數(shù)
void addOnMultiSelectOutOfSizeListener(OnMultiSelectOutOfSize listener) {
  this.multiSelectOutOfSize = listener;
}
利用controller來(lái)控制日歷的切換,支持配置動(dòng)畫(huà)
//跳轉(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();
//切換到下一個(gè)月份,
void moveToNextMonth();
//切換到上一個(gè)月份
void moveToPreviousMonth();
利用controller來(lái)獲取日歷的一些數(shù)據(jù)信息
// 獲取當(dāng)前的月份
DateTime getCurrentMonth();
//獲取被選中的日期,多選
Set getMultiSelectCalendar();
//獲取被選中的日期,單選
DateModel getSingleSelectCalendar();
自定義UI

包括自定義WeekBar、自定義日歷Item,默認(rèn)使用的都是DefaultXXXWidget。

只要繼承對(duì)應(yīng)的Base類(lèi),實(shí)現(xiàn)相應(yīng)的方法,然后只需要在配置Controller的時(shí)候,實(shí)現(xiàn)相應(yīng)的Builder方法就可以了。

//支持自定義繪制
DayWidgetBuilder dayWidgetBuilder; //創(chuàng)建日歷item
WeekBarItemWidgetBuilder weekBarItemWidgetBuilder; //創(chuàng)建頂部的weekbar
自定義WeekBar

繼承BaseWeekBar,重寫(xiě)getWeekBarItem(index)方法就可以。隨便你怎么實(shí)現(xiàn),只需要返回一個(gè)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的方式來(lái)創(chuàng)建,一種是利用Canvas來(lái)自定義繪制Item。最后只需要在CalendarController的構(gòu)造參數(shù)中進(jìn)行配置就可以了。

繼承BaseCombineDayWidget,重寫(xiě)getNormalWidget(DateModel dateModel) 和getSelectedWidget(DateModel dateModel)就可以了,返回對(duì)應(yīng)的widget就行。

class DefaultCombineDayWidget extends BaseCombineDayWidget {
  DefaultCombineDayWidget(DateModel dateModel) : super(dateModel);

  @override
  Widget getNormalWidget(DateModel dateModel) {
     //實(shí)現(xiàn)默認(rèn)狀態(tài)下的UI
  }

  @override
  Widget getSelectedWidget(DateModel dateModel) {
    //繪制被選中的UI
  }
}

繼承BaseCustomDayWidget,重寫(xiě)drawNormal和drawSelected的兩個(gè)方法就可以了,利用canvas自己繪制Item。

class DefaultCustomDayWidget extends BaseCustomDayWidget {
  DefaultCustomDayWidget(DateModel dateModel) : super(dateModel);
  @override
  void drawNormal(DateModel dateModel, Canvas canvas, Size size) {
    //實(shí)現(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實(shí)體類(lèi)

日歷所用的日期的實(shí)體類(lèi)DateModel,有下面這些屬性。

/**
 * 日期的實(shí)體類(lèi)
 */
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),比如可以實(shí)現(xiàn)在某個(gè)范圍外,設(shè)置置灰的功能
  bool isSelected; //是否被選中,用來(lái)實(shí)現(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)建對(duì)應(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)化代碼實(shí)現(xiàn)

支持屏蔽指定的某些天

繼續(xù)寫(xiě)幾個(gè)不同風(fēng)格的Demo

支持周視圖

支持動(dòng)畫(huà)切換周視圖和月視圖

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/6883.html

相關(guān)文章

  • Flutter基礎(chǔ)(二)Flutter最新開(kāi)發(fā)環(huán)境搭建和Hello World

    摘要:注釋處的方法是程序的入口,使用了符號(hào),這是中單行函數(shù)或方法的簡(jiǎn)寫(xiě),等價(jià)于如下代碼方法是框架的入口,如果不返回方法,那么執(zhí)行的是一個(gè)控制臺(tái)應(yīng)用。 本文首發(fā)于微信公眾號(hào)「劉望舒」 前言 最近的Google I/O大會(huì)上,F(xiàn)lutter1.5 開(kāi)始支持移動(dòng)、Web、桌面和嵌入式設(shè)備,從不溫不火的sky一直進(jìn)化到如今熱門(mén)的Flutter,F(xiàn)lutter的發(fā)展已經(jīng)超出很多人的想象。我對(duì)跨平臺(tái)技術(shù)一...

    tuomao 評(píng)論0 收藏0
  • 【開(kāi)發(fā)經(jīng)驗(yàn)】Flutter避免代碼嵌套,寫(xiě)好build方法

    摘要:意味著屬性必須在構(gòu)造函數(shù)中就被初始化完成,不接受提前定義,也不接受更改。所以,在生命周期中動(dòng)態(tài)的改變對(duì)象的屬性是不可能的,必須使用框架的方法來(lái)為構(gòu)造函數(shù)動(dòng)態(tài)指定參數(shù),從而達(dá)到改變組件屬性的功能。 本文適合使用Flutter開(kāi)發(fā)過(guò)一段時(shí)間的開(kāi)發(fā)者閱讀,旨在分享一種避免Flutter的UI代碼嵌套太深問(wèn)題的方法。如果對(duì)本文內(nèi)容或觀點(diǎn)有相關(guān)疑問(wèn),歡迎在評(píng)論中指出。 優(yōu)化效果(縮略圖): sh...

    Worktile 評(píng)論0 收藏0
  • 深入理解flutter的編譯原理與優(yōu)化

    摘要:本文將以一個(gè)簡(jiǎn)單的為例,介紹下相關(guān)原理及定制與優(yōu)化。模式對(duì)應(yīng)了的模式,又稱(chēng)檢查模式或者慢速模式。為快速啟動(dòng),快速執(zhí)行,包大小做了優(yōu)化。并不支持模擬器的原因在于,模擬器上的診斷并不代表真實(shí)的性能。因此本文主要討論因引入的構(gòu)建,運(yùn)行等原理。 摘要: 閑魚(yú)技術(shù)-正物 問(wèn)題背景 對(duì)于開(kāi)發(fā)者而言,什么是Flutter?它是用什么語(yǔ)言編寫(xiě)的,包含哪幾部分,是如何被編譯,運(yùn)行到設(shè)備上的呢?Flutt...

    codecook 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<