Forráskód Böngészése

refactor PR commit

Liu Yanbo 7 éve
szülő
commit
4f5e4a7359

+ 2 - 1
CHANGELOG.md

@@ -13,4 +13,5 @@
 ## [1.0.1] - fix day bug when changing month
 ## [1.0.2] - add Dutch support
 ## [1.0.3] - add Dutch in demo
-## [1.0.4] - add Dutch in readme
+## [1.0.4] - add Dutch in readme
+## [1.0.5] - add max/min time limit for Date Picker, add theme

+ 8 - 5
README.md

@@ -15,11 +15,14 @@ you can choose date / time / date&time in English, Dutch and Chinese, and you ca
 ```
 FlatButton(
     onPressed: () {
-        DatePicker.showDateTimePicker(context, showTitleActions: true, onChanged: (date) {
-            print('change $date');
-        }, onConfirm: (date) {
-            print('confirm $date');
-        }, currentTime: DateTime(2008, 12, 31, 23, 12, 34), locale: 'zh');
+        DatePicker.showDatePicker(context,
+                              showTitleActions: true,
+                              minTime: DateTime(2018, 3, 5),
+                              maxTime: DateTime(2019, 6, 7), onChanged: (date) {
+                            print('change $date');
+                          }, onConfirm: (date) {
+                            print('confirm $date');
+                          }, currentTime: DateTime.now(), locale: LocaleType.zh);
     },
     child: Text(
         'show date time picker (Chinese)',

+ 6 - 10
example/lib/main.dart

@@ -10,14 +10,6 @@ class MyApp extends StatelessWidget {
     return new MaterialApp(
       title: 'Flutter Demo',
       theme: new ThemeData(
-        // This is the theme of your application.
-        //
-        // Try running your application with "flutter run". You'll see the
-        // application has a blue toolbar. Then, without quitting the app, try
-        // changing the primarySwatch below to Colors.green and then invoke
-        // "hot reload" (press "r" in the console where you ran "flutter run",
-        // or press Run > Flutter Hot Reload in IntelliJ). Notice that the
-        // counter didn't reset back to zero; the application is not restarted.
         primarySwatch: Colors.blue,
       ),
       home: new HomePage(),
@@ -37,11 +29,15 @@ class HomePage extends StatelessWidget {
           children: <Widget>[
             FlatButton(
                 onPressed: () {
-                  DatePicker.showDatePicker(context, showTitleActions: true, onChanged: (date) {
+                  DatePicker.showDatePicker(context,
+                      showTitleActions: true,
+                      minTime: DateTime(2018, 3, 5),
+                      maxTime: DateTime(2019, 6, 7),
+                      theme: DatePickerTheme(), onChanged: (date) {
                     print('change $date');
                   }, onConfirm: (date) {
                     print('confirm $date');
-                  }, currentTime: DateTime(2008, 12, 31, 23, 12, 34), locale: LocaleType.zh);
+                  }, currentTime: DateTime.now(), locale: LocaleType.zh);
                 },
                 child: Text(
                   'show date picker',

+ 62 - 35
lib/flutter_datetime_picker.dart

@@ -20,8 +20,8 @@ class DatePicker {
   static void showDatePicker(
     BuildContext context, {
     bool showTitleActions: true,
-    DateTime min,
-    DateTime max,
+    DateTime minTime,
+    DateTime maxTime,
     DateChangedCallback onChanged,
     DateChangedCallback onConfirm,
     locale: LocaleType.en,
@@ -37,7 +37,8 @@ class DatePicker {
             locale: locale,
             theme: theme,
             barrierLabel: MaterialLocalizations.of(context).modalBarrierDismissLabel,
-            pickerModel: DatePickerModel(currentTime: currentTime, max: max, min: min, locale: locale)));
+            pickerModel: DatePickerModel(
+                currentTime: currentTime, maxTime: maxTime, minTime: minTime, locale: locale)));
   }
 
   ///
@@ -46,8 +47,6 @@ class DatePicker {
   static void showTimePicker(
     BuildContext context, {
     bool showTitleActions: true,
-    DateTime min,
-    DateTime max,
     DateChangedCallback onChanged,
     DateChangedCallback onConfirm,
     locale: LocaleType.en,
@@ -63,7 +62,7 @@ class DatePicker {
             locale: locale,
             theme: theme,
             barrierLabel: MaterialLocalizations.of(context).modalBarrierDismissLabel,
-            pickerModel: TimePickerModel(currentTime: currentTime, max: max, min: min, locale: locale)));
+            pickerModel: TimePickerModel(currentTime: currentTime, locale: locale)));
   }
 
   ///
@@ -122,12 +121,13 @@ class _DatePickerRoute<T> extends PopupRoute<T> {
     this.showTitleActions,
     this.onChanged,
     this.onConfirm,
-    this.theme,
+    theme,
     this.barrierLabel,
     this.locale,
     RouteSettings settings,
     pickerModel,
   })  : this.pickerModel = pickerModel ?? DatePickerModel(),
+        this.theme = theme ?? DatePickerTheme(),
         super(settings: settings);
 
   final bool showTitleActions;
@@ -147,7 +147,7 @@ class _DatePickerRoute<T> extends PopupRoute<T> {
   final String barrierLabel;
 
   @override
-  Color get barrierColor => theme?.barrierColor ?? Colors.black54;
+  Color get barrierColor => Colors.black54;
 
   AnimationController _animationController;
 
@@ -159,7 +159,8 @@ class _DatePickerRoute<T> extends PopupRoute<T> {
   }
 
   @override
-  Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
+  Widget buildPage(
+      BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
     Widget bottomSheet = new MediaQuery.removePadding(
       context: context,
       removeTop: true,
@@ -170,15 +171,17 @@ class _DatePickerRoute<T> extends PopupRoute<T> {
         pickerModel: pickerModel,
       ),
     );
-    if (theme != null) {
-      bottomSheet = new Theme(data: Theme.of(context, shadowThemeOnly: true), child: bottomSheet);
+    ThemeData inheritTheme = Theme.of(context, shadowThemeOnly: true);
+    if (inheritTheme != null) {
+      bottomSheet = new Theme(data: inheritTheme, child: bottomSheet);
     }
     return bottomSheet;
   }
 }
 
 class _DatePickerComponent extends StatefulWidget {
-  _DatePickerComponent({Key key, @required this.route, this.onChanged, this.locale, this.pickerModel});
+  _DatePickerComponent(
+      {Key key, @required this.route, this.onChanged, this.locale, this.pickerModel});
 
   final DateChangedCallback onChanged;
 
@@ -204,24 +207,25 @@ class _DatePickerState extends State<_DatePickerComponent> {
   }
 
   void refreshScrollOffset() {
-    leftScrollCtrl = new FixedExtentScrollController(initialItem: widget.pickerModel.currentLeftIndex());
-    middleScrollCtrl = new FixedExtentScrollController(initialItem: widget.pickerModel.currentMiddleIndex());
-    rightScrollCtrl = new FixedExtentScrollController(initialItem: widget.pickerModel.currentRightIndex());
+    leftScrollCtrl =
+        new FixedExtentScrollController(initialItem: widget.pickerModel.currentLeftIndex());
+    middleScrollCtrl =
+        new FixedExtentScrollController(initialItem: widget.pickerModel.currentMiddleIndex());
+    rightScrollCtrl =
+        new FixedExtentScrollController(initialItem: widget.pickerModel.currentRightIndex());
   }
 
   @override
   Widget build(BuildContext context) {
-    DatePickerTheme theme = DefaultDatePickerTheme.of(context).theme;
-    if (widget.route.theme != null) {
-      theme = widget.route.theme.merge(theme);
-    }
+    DatePickerTheme theme = widget.route.theme;
     return new GestureDetector(
       child: new AnimatedBuilder(
         animation: widget.route.animation,
         builder: (BuildContext context, Widget child) {
           return new ClipRect(
             child: new CustomSingleChildLayout(
-              delegate: new _BottomPickerLayout(widget.route.animation.value, theme, showTitleActions: widget.route.showTitleActions),
+              delegate: new _BottomPickerLayout(widget.route.animation.value, theme,
+                  showTitleActions: widget.route.showTitleActions),
               child: new GestureDetector(
                 child: Material(
                   color: Colors.transparent,
@@ -254,14 +258,20 @@ class _DatePickerState extends State<_DatePickerComponent> {
     return itemView;
   }
 
-  Widget _renderColumnView(ValueKey key, DatePickerTheme theme, StringAtIndexCallBack stringAtIndexCB, ScrollController scrollController, int layoutProportion,
-      ValueChanged<int> selectedChangedWhenScrolling, ValueChanged<int> selectedChangedWhenScrollEnd) {
+  Widget _renderColumnView(
+      ValueKey key,
+      DatePickerTheme theme,
+      StringAtIndexCallBack stringAtIndexCB,
+      ScrollController scrollController,
+      int layoutProportion,
+      ValueChanged<int> selectedChangedWhenScrolling,
+      ValueChanged<int> selectedChangedWhenScrollEnd) {
     return Expanded(
       flex: layoutProportion,
       child: Container(
           padding: EdgeInsets.all(8.0),
           height: theme.containerHeight,
-          decoration: BoxDecoration(color: theme?.backgroundColor ?? Colors.white),
+          decoration: BoxDecoration(color: theme.backgroundColor ?? Colors.white),
           child: NotificationListener(
               onNotification: (ScrollNotification notification) {
                 if (notification.depth == 0 &&
@@ -276,7 +286,7 @@ class _DatePickerState extends State<_DatePickerComponent> {
               },
               child: CupertinoPicker.builder(
                   key: key,
-                  backgroundColor: theme?.backgroundColor ?? Colors.white,
+                  backgroundColor: theme.backgroundColor ?? Colors.white,
                   scrollController: scrollController,
                   itemExtent: theme.itemHeight,
                   onSelectedItemChanged: (int index) {
@@ -293,7 +303,7 @@ class _DatePickerState extends State<_DatePickerComponent> {
                       alignment: Alignment.center,
                       child: Text(
                         content,
-                        style: theme?.itemStyle,
+                        style: theme.itemStyle,
                         textAlign: TextAlign.start,
                       ),
                     );
@@ -303,11 +313,15 @@ class _DatePickerState extends State<_DatePickerComponent> {
 
   Widget _renderItemView(DatePickerTheme theme) {
     return Container(
-      color: theme?.backgroundColor ?? Colors.white,
+      color: theme.backgroundColor ?? Colors.white,
       child: Row(
         mainAxisAlignment: MainAxisAlignment.spaceBetween,
         children: <Widget>[
-          _renderColumnView(ValueKey(widget.pickerModel.currentLeftIndex()), theme, widget.pickerModel.leftStringAtIndex, leftScrollCtrl,
+          _renderColumnView(
+              ValueKey(widget.pickerModel.currentLeftIndex()),
+              theme,
+              widget.pickerModel.leftStringAtIndex,
+              leftScrollCtrl,
               widget.pickerModel.layoutProportions()[0], (index) {
             widget.pickerModel.setLeftIndex(index);
           }, (index) {
@@ -318,9 +332,13 @@ class _DatePickerState extends State<_DatePickerComponent> {
           }),
           Text(
             widget.pickerModel.leftDivider(),
-            style: theme?.itemStyle,
+            style: theme.itemStyle,
           ),
-          _renderColumnView(ValueKey(widget.pickerModel.currentLeftIndex()), theme, widget.pickerModel.middleStringAtIndex, middleScrollCtrl,
+          _renderColumnView(
+              ValueKey(widget.pickerModel.currentLeftIndex()),
+              theme,
+              widget.pickerModel.middleStringAtIndex,
+              middleScrollCtrl,
               widget.pickerModel.layoutProportions()[1], (index) {
             widget.pickerModel.setMiddleIndex(index);
           }, (index) {
@@ -331,9 +349,14 @@ class _DatePickerState extends State<_DatePickerComponent> {
           }),
           Text(
             widget.pickerModel.rightDivider(),
-            style: theme?.itemStyle,
+            style: theme.itemStyle,
           ),
-          _renderColumnView(ValueKey(widget.pickerModel.currentMiddleIndex()), theme, widget.pickerModel.rightStringAtIndex, rightScrollCtrl,
+          _renderColumnView(
+              ValueKey(
+                  widget.pickerModel.currentMiddleIndex() + widget.pickerModel.currentLeftIndex()),
+              theme,
+              widget.pickerModel.rightStringAtIndex,
+              rightScrollCtrl,
               widget.pickerModel.layoutProportions()[2], (index) {
             widget.pickerModel.setRightIndex(index);
             _notifyDateChanged();
@@ -350,7 +373,7 @@ class _DatePickerState extends State<_DatePickerComponent> {
 
     return Container(
       height: theme.titleHeight,
-      decoration: BoxDecoration(color: theme?.backgroundColor ?? Colors.white),
+      decoration: BoxDecoration(color: theme.backgroundColor ?? Colors.white),
       child: Row(
         mainAxisAlignment: MainAxisAlignment.spaceBetween,
         children: <Widget>[
@@ -359,7 +382,7 @@ class _DatePickerState extends State<_DatePickerComponent> {
             child: FlatButton(
               child: Text(
                 '$cancel',
-                style: theme?.cancelStyle,
+                style: theme.cancelStyle,
               ),
               onPressed: () => Navigator.pop(context),
             ),
@@ -369,7 +392,7 @@ class _DatePickerState extends State<_DatePickerComponent> {
             child: FlatButton(
               child: Text(
                 '$done',
-                style: theme?.doneStyle,
+                style: theme.doneStyle,
               ),
               onPressed: () {
                 if (widget.route.onConfirm != null) {
@@ -408,7 +431,11 @@ class _BottomPickerLayout extends SingleChildLayoutDelegate {
       maxHeight += theme.titleHeight;
     }
 
-    return new BoxConstraints(minWidth: constraints.maxWidth, maxWidth: constraints.maxWidth, minHeight: 0.0, maxHeight: maxHeight);
+    return new BoxConstraints(
+        minWidth: constraints.maxWidth,
+        maxWidth: constraints.maxWidth,
+        minHeight: 0.0,
+        maxHeight: maxHeight);
   }
 
   @override

+ 113 - 156
lib/src/date_model.dart

@@ -1,30 +1,23 @@
 import 'package:flutter_datetime_picker/src/date_format.dart';
 import 'package:flutter_datetime_picker/src/i18n_model.dart';
-import 'package:flutter_commons_lang/flutter_commons_lang.dart';
+import 'datetime_util.dart';
 
 abstract class BasePickerModel {
   String leftStringAtIndex(int index);
-
   String middleStringAtIndex(int index);
-
   String rightStringAtIndex(int index);
 
   void setLeftIndex(int index);
-
   void setMiddleIndex(int index);
-
   void setRightIndex(int index);
 
   int currentLeftIndex();
-
   int currentMiddleIndex();
-
   int currentRightIndex();
 
   DateTime finalTime();
 
   String leftDivider();
-
   String rightDivider();
 
   List<int> layoutProportions();
@@ -110,52 +103,70 @@ class CommonPickerModel extends BasePickerModel {
 }
 
 class DatePickerModel extends CommonPickerModel {
-  DateTime max;
-  DateTime min;
-  int maxYear;
-  int minYear;
-  int maxMonth;
-  int minMonth;
-  int maxDay;
-  int minDay;
-
-  DatePickerModel({DateTime currentTime, this.max, this.min, LocaleType locale}) : super(locale: locale) {
+  DateTime maxTime;
+  DateTime minTime;
+
+  DatePickerModel({DateTime currentTime, DateTime maxTime, DateTime minTime, LocaleType locale})
+      : super(locale: locale) {
+    this.maxTime = maxTime ?? DateTime(2049, 12, 31);
+    this.minTime = minTime ?? DateTime(1970, 1, 1);
+
+    currentTime = currentTime ?? DateTime.now();
     if (currentTime != null) {
-      if (max != null && currentTime.compareTo(max) > 0) {
-        currentTime = max;
-      } else if (min != null && currentTime.compareTo(min) < 0) {
-        currentTime = min;
+      if (currentTime.compareTo(this.maxTime) > 0) {
+        currentTime = this.maxTime;
+      } else if (currentTime.compareTo(this.minTime) < 0) {
+        currentTime = this.minTime;
       }
     }
-    this.currentTime = currentTime ?? DateTime.now();
+    this.currentTime = currentTime;
+
     fillLeftLists();
     fillMiddleLists();
     fillRightLists();
-    _currentLeftIndex = this.currentTime.year - minYear;
+    int minMonth = minMonthOfCurrentYear();
+    int minDay = minDayOfCurrentMonth();
+    _currentLeftIndex = this.currentTime.year - this.minTime.year;
     _currentMiddleIndex = this.currentTime.month - minMonth;
     _currentRightIndex = this.currentTime.day - minDay;
   }
 
   void fillLeftLists() {
-    maxYear = max?.year ?? 2050;
-    minYear = min?.year ?? 1970;
-    this.leftList = List.generate(maxYear - minYear + 1, (int index) {
-      return '${minYear + index}${_localeYear()}';
+    this.leftList = List.generate(maxTime.year - minTime.year + 1, (int index) {
+      return '${minTime.year + index}${_localeYear()}';
     });
   }
 
+  int maxMonthOfCurrentYear() {
+    return currentTime.year == maxTime.year ? maxTime.month : 12;
+  }
+
+  int minMonthOfCurrentYear() {
+    return currentTime.year == minTime.year ? minTime.month : 1;
+  }
+
+  int maxDayOfCurrentMonth() {
+    int dayCount = calcDateCount(currentTime.year, currentTime.month);
+    return currentTime.year == maxTime.year && currentTime.month == maxTime.month
+        ? maxTime.day
+        : dayCount;
+  }
+
+  int minDayOfCurrentMonth() {
+    return currentTime.year == minTime.year && currentTime.month == minTime.month ? minTime.day : 1;
+  }
+
   void fillMiddleLists() {
-    minMonth = DateUtils.truncatedEquals(currentTime, min, DateUtils.YEAR) ? min?.month : 1;
-    maxMonth = DateUtils.truncatedEquals(currentTime, max, DateUtils.YEAR) ? max.month : 12;
+    int minMonth = minMonthOfCurrentYear();
+    int maxMonth = maxMonthOfCurrentYear();
     this.middleList = List.generate(maxMonth - minMonth + 1, (int index) {
       return '${minMonth + index}${_localeMonth()}';
     });
   }
 
   void fillRightLists() {
-    int dayCount = DateUtils.daysOfTheMonth(currentTime);
-    maxDay = DateUtils.truncatedEquals(currentTime, max, DateUtils.MONTH) ? max.day : dayCount;
-    minDay = DateUtils.truncatedEquals(currentTime, min, DateUtils.MONTH) ? min.day : 1;
+    int maxDay = maxDayOfCurrentMonth();
+    int minDay = minDayOfCurrentMonth();
     this.rightList = List.generate(maxDay - minDay + 1, (int index) {
       return '${minDay + index}${_localeDay()}';
     });
@@ -163,43 +174,79 @@ class DatePickerModel extends CommonPickerModel {
 
   @override
   void setLeftIndex(int index) {
-    if (index - minYear > maxYear) index = maxYear - minYear;
     super.setLeftIndex(index);
-    int month = currentTime.month;
-    currentTime = DateUtils.set(currentTime, year: index + minYear);
-    fillMiddleLists();
-
-    if (month > maxMonth) {
-      setMiddleIndex(maxMonth - minMonth);
-    } else if (month < minMonth) {
-      setMiddleIndex(0);
+    //adjust middle
+    int destYear = index + minTime.year;
+    int minMonth = minMonthOfCurrentYear();
+    DateTime newTime;
+    //change date time
+    if (currentTime.month == 2 && currentTime.day == 29) {
+      newTime = DateTime(
+        destYear,
+        currentTime.month,
+        calcDateCount(destYear, 2),
+      );
     } else {
-      setMiddleIndex(month - minMonth);
+      newTime = DateTime(
+        destYear,
+        currentTime.month,
+        currentTime.day,
+      );
     }
+    //min/max check
+    if (newTime.isAfter(maxTime)) {
+      currentTime = maxTime;
+    } else if (newTime.isBefore(minTime)) {
+      currentTime = minTime;
+    } else {
+      currentTime = newTime;
+    }
+
+    fillMiddleLists();
+    fillRightLists();
+    minMonth = minMonthOfCurrentYear();
+    int minDay = minDayOfCurrentMonth();
+    _currentMiddleIndex = currentTime.month - minMonth;
+    _currentRightIndex = currentTime.day - minDay;
   }
 
   @override
   void setMiddleIndex(int index) {
-    if (index - minMonth > maxMonth) index = maxMonth - minMonth;
     super.setMiddleIndex(index);
-    int day = currentTime.day;
-    currentTime = DateUtils.set(currentTime, month: index + minMonth, day: 1);
-    fillRightLists();
-
-    if (day > maxDay) {
-      setRightIndex(maxDay - minDay);
-    } else if (day < minDay) {
-      setRightIndex(0);
+    //adjust right
+    int minMonth = minMonthOfCurrentYear();
+    int destMonth = minMonth + index;
+    DateTime newTime;
+    //change date time
+    int dayCount = calcDateCount(currentTime.year, destMonth);
+    newTime = DateTime(
+      currentTime.year,
+      destMonth,
+      currentTime.day <= dayCount ? currentTime.day : dayCount,
+    );
+    //min/max check
+    if (newTime.isAfter(maxTime)) {
+      currentTime = maxTime;
+    } else if (newTime.isBefore(minTime)) {
+      currentTime = minTime;
     } else {
-      setRightIndex(day - minDay);
+      currentTime = newTime;
     }
+
+    fillRightLists();
+    int minDay = minDayOfCurrentMonth();
+    _currentRightIndex = currentTime.day - minDay;
   }
 
   @override
   void setRightIndex(int index) {
-    if (index - minDay > maxDay) index = maxDay - minDay;
     super.setRightIndex(index);
-    currentTime = DateUtils.set(currentTime, day: index + minDay);
+    int minDay = minDayOfCurrentMonth();
+    currentTime = DateTime(
+      currentTime.year,
+      currentTime.month,
+      minDay + index,
+    );
   }
 
   @override
@@ -255,114 +302,23 @@ class DatePickerModel extends CommonPickerModel {
 
   @override
   DateTime finalTime() {
-    final year = _currentLeftIndex + minYear;
-    final month = _currentMiddleIndex + minMonth;
-    final day = _currentRightIndex + 1;
-    return DateTime(year, month, day);
+    return currentTime;
   }
 }
 
 class TimePickerModel extends CommonPickerModel {
-  DateTime max;
-  DateTime min;
-  int maxHour;
-  int minHour;
-  int maxMinute;
-  int minMinute;
-  int maxSecond;
-  int minSecond;
-
-  TimePickerModel({DateTime currentTime, this.max, this.min, LocaleType locale}) : super(locale: locale) {
-    if (currentTime != null) {
-      if (max != null && currentTime.compareTo(max) > 0) {
-        currentTime = max;
-      } else if (min != null && currentTime.compareTo(min) < 0) {
-        currentTime = min;
-      }
-    }
+  TimePickerModel({DateTime currentTime, LocaleType locale}) : super(locale: locale) {
     this.currentTime = currentTime ?? DateTime.now();
 
-    maxHour = max?.hour ?? 23;
-    minHour = min?.hour ?? 0;
-    maxMinute = DateUtils.truncatedEquals(currentTime, max, DateUtils.MINUTE) ? max.minute : 59;
-    minMinute = DateUtils.truncatedEquals(currentTime, min, DateUtils.MINUTE) ? min?.minute : 0;
-
     _currentLeftIndex = this.currentTime.hour;
     _currentMiddleIndex = this.currentTime.minute;
     _currentRightIndex = this.currentTime.second;
-
-    fillLeftLists();
-    fillMiddleLists();
-    fillRightLists();
-  }
-
-  void fillLeftLists() {
-    this.leftList = List.generate(maxHour - minHour + 1, (int index) {
-      return digits(minHour + index, 2);
-    });
-  }
-
-  void fillMiddleLists() {
-    maxMinute = DateUtils.truncatedEquals(currentTime, max, DateUtils.HOUR) ? max?.minute : 59;
-    minMinute = DateUtils.truncatedEquals(currentTime, min, DateUtils.HOUR) ? min?.minute : 0;
-    this.middleList = List.generate(maxMinute - minMinute + 1, (int index) {
-      return digits(minMinute + index, 2);
-    });
-  }
-
-  void fillRightLists() {
-    maxSecond = DateUtils.truncatedEquals(currentTime, max, DateUtils.MINUTE) ? max.second : 59;
-    minSecond = DateUtils.truncatedEquals(currentTime, min, DateUtils.MINUTE) ? min.second : 0;
-    this.rightList = List.generate(maxSecond - minSecond + 1, (int index) {
-      return digits(minSecond + index, 2);
-    });
-  }
-
-  @override
-  void setLeftIndex(int index) {
-    if (index - minHour > maxHour) index = maxHour - minHour;
-    super.setLeftIndex(index);
-    int minute = currentTime.minute;
-    currentTime = DateUtils.set(currentTime, hour: index + minHour);
-    fillMiddleLists();
-
-    if (minute > maxMinute) {
-      setMiddleIndex(maxMinute - minMinute);
-    } else if (minute < minMinute) {
-      setMiddleIndex(0);
-    } else {
-      setMiddleIndex(minute - minMinute);
-    }
-  }
-
-  @override
-  void setMiddleIndex(int index) {
-    if (index - minMinute > maxMinute) index = maxMinute - minMinute;
-    super.setMiddleIndex(index);
-    int second = currentTime.second;
-    currentTime = DateUtils.set(currentTime, minute: index + minMinute, second: 1);
-    fillRightLists();
-
-    if (second > maxSecond) {
-      setRightIndex(maxSecond - minSecond);
-    } else if (second < minSecond) {
-      setRightIndex(0);
-    } else {
-      setRightIndex(second - minSecond);
-    }
-  }
-
-  @override
-  void setRightIndex(int index) {
-    if (index - minSecond > maxSecond) index = maxSecond - minSecond;
-    super.setRightIndex(index);
-    currentTime = DateUtils.set(currentTime, second: index + minSecond);
   }
 
   @override
   String leftStringAtIndex(int index) {
-    if (index >= 0 && index < leftList.length) {
-      return leftList[index];
+    if (index >= 0 && index < 24) {
+      return digits(index, 2);
     } else {
       return null;
     }
@@ -370,8 +326,8 @@ class TimePickerModel extends CommonPickerModel {
 
   @override
   String middleStringAtIndex(int index) {
-    if (index >= 0 && index < middleList.length) {
-      return middleList[index];
+    if (index >= 0 && index < 60) {
+      return digits(index, 2);
     } else {
       return null;
     }
@@ -379,8 +335,8 @@ class TimePickerModel extends CommonPickerModel {
 
   @override
   String rightStringAtIndex(int index) {
-    if (index >= 0 && index < rightList.length) {
-      return rightList[index];
+    if (index >= 0 && index < 60) {
+      return digits(index, 2);
     } else {
       return null;
     }
@@ -398,7 +354,8 @@ class TimePickerModel extends CommonPickerModel {
 
   @override
   DateTime finalTime() {
-    return DateTime(currentTime.year, currentTime.month, currentTime.day, _currentLeftIndex, _currentMiddleIndex, _currentRightIndex);
+    return DateTime(currentTime.year, currentTime.month, currentTime.day, _currentLeftIndex,
+        _currentMiddleIndex, _currentRightIndex);
   }
 }
 
@@ -442,7 +399,7 @@ class DateTimePickerModel extends CommonPickerModel {
 
   @override
   List<int> layoutProportions() {
-    return [3, 1, 1];
+    return [4, 1, 1];
   }
 
   @override

+ 4 - 156
lib/src/datetime_picker_theme.dart

@@ -2,174 +2,22 @@ import 'package:flutter/foundation.dart';
 import 'package:flutter/material.dart';
 
 class DatePickerTheme extends Diagnosticable {
-  /// Whether null values are replaced with their value in an ancestor text
-  /// style (e.g., in a [TextSpan] tree).
-  ///
-  /// If this is false, properties that don't have explicit values will revert
-  /// to the defaults: white in color, a font size of 10 pixels, in a sans-serif
-  /// font face.
-  final bool inherit;
-
   final TextStyle cancelStyle;
   final TextStyle doneStyle;
   final TextStyle itemStyle;
   final Color backgroundColor;
-  final Color barrierColor;
 
   final double containerHeight;
   final double titleHeight;
   final double itemHeight;
 
   const DatePickerTheme({
-    this.inherit,
-    this.cancelStyle,
-    this.doneStyle,
-    this.itemStyle,
-    this.backgroundColor,
-    this.barrierColor,
+    this.cancelStyle = const TextStyle(color: Colors.black54, fontSize: 16),
+    this.doneStyle = const TextStyle(color: Colors.blue, fontSize: 16),
+    this.itemStyle = const TextStyle(color: Color(0xFF000046), fontSize: 18),
+    this.backgroundColor = Colors.white,
     this.containerHeight = 210.0,
     this.titleHeight = 44.0,
     this.itemHeight = 36.0,
   });
-
-  /// Creates a copy of this theme data but with the given fields replaced with
-  /// the new values.
-  DatePickerTheme copyWith({
-    TextStyle cancelStyle,
-    TextStyle doneStyle,
-    TextStyle itemStyle,
-    Color backgroundColor,
-    Color barrierColor,
-    double pickerHeight,
-    double pickerTitleHeight,
-    double pickerItemHeight,
-  }) {
-    return DatePickerTheme(
-      inherit: inherit,
-      cancelStyle: cancelStyle != null ? cancelStyle.merge(this.cancelStyle) : this.cancelStyle,
-      doneStyle: doneStyle != null ? doneStyle.merge(this.doneStyle) : this.doneStyle,
-      itemStyle: itemStyle != null ? itemStyle.merge(this.itemStyle) : this.itemStyle,
-      backgroundColor: backgroundColor ?? this.backgroundColor,
-      barrierColor: barrierColor ?? this.barrierColor,
-      containerHeight: pickerHeight ?? this.containerHeight,
-      titleHeight: pickerTitleHeight ?? this.titleHeight,
-      itemHeight: pickerItemHeight ?? this.itemHeight,
-    );
-  }
-
-  /// Returns a new theme data that is a combination of this style and the given
-  /// [other] style.
-  ///
-  /// If the given [other] theme data has its [DatePickerTheme.inherit] set to true,
-  /// its null properties are replaced with the non-null properties of this text
-  /// style. The [other] style _inherits_ the properties of this style. Another
-  /// way to think of it is that the "missing" properties of the [other] style
-  /// are _filled_ by the properties of this style.
-  ///
-  /// If the given [other] theme data has its [DatePickerTheme.inherit] set to false,
-  /// returns the given [other] style unchanged. The [other] style does not
-  /// inherit properties of this style.
-  ///
-  /// If the given theme data is null, returns this theme data.
-  DatePickerTheme merge(DatePickerTheme other) {
-    if (other == null) return this;
-    if (!other.inherit) return other;
-
-    return copyWith(
-      cancelStyle: other.cancelStyle,
-      doneStyle: other.doneStyle,
-      itemStyle: other.itemStyle,
-      backgroundColor: other.backgroundColor,
-      barrierColor: other.barrierColor,
-      pickerHeight: other.containerHeight,
-      pickerTitleHeight: other.titleHeight,
-      pickerItemHeight: other.itemHeight,
-    );
-  }
-}
-
-/// The theme data to apply to descendant [DatePicker] widgets without explicit style.
-class DefaultDatePickerTheme extends InheritedWidget {
-  /// Creates a default theme data for the given subtree.
-  ///
-  /// Consider using [DefaultDatePickerTheme.merge] to inherit styling information
-  /// from the current default theme data for a given [BuildContext].
-  ///
-  const DefaultDatePickerTheme({
-    Key key,
-    @required this.theme,
-    @required Widget child,
-  })  : assert(theme != null),
-        assert(child != null),
-        super(key: key, child: child);
-
-  /// A const-constructible default theme data that provides fallback values.
-  ///
-  /// Returned from [of] when the given [BuildContext] doesn't have an enclosing default theme data.
-  ///
-  /// This constructor creates a [DefaultDatePickerTheme] that lacks a [child], which
-  /// means the constructed value cannot be incorporated into the tree.
-  const DefaultDatePickerTheme.fallback() : theme = const DatePickerTheme();
-
-  /// Creates a default theme data that overrides the theme datas in scope at
-  /// this point in the widget tree.
-  ///
-  /// The given [style] is merged with the [style] from the default theme data
-  /// for the [BuildContext] where the widget is inserted, and any of the other
-  /// arguments that are not null replace the corresponding properties on that
-  /// same default theme data.
-  ///
-  /// This constructor cannot be used to override the [maxLines] property of the
-  /// ancestor with the value null, since null here is used to mean "defer to
-  /// ancestor". To replace a non-null [maxLines] from an ancestor with the null
-  /// value (to remove the restriction on number of lines), manually obtain the
-  /// ambient [DefaultDatePickerTheme] using [DefaultDatePickerTheme.of], then create a new
-  /// [DefaultDatePickerTheme] using the [new DefaultDatePickerTheme] constructor directly.
-  /// See the source below for an example of how to do this (since that's
-  /// essentially what this constructor does).
-  static Widget merge({
-    Key key,
-    DatePickerTheme theme,
-    @required Widget child,
-  }) {
-    assert(child != null);
-    return Builder(
-      builder: (BuildContext context) {
-        final DefaultDatePickerTheme parent = DefaultDatePickerTheme.of(context);
-        return DefaultDatePickerTheme(
-          key: key,
-          theme: parent.theme.merge(theme),
-          child: child,
-        );
-      },
-    );
-  }
-
-  /// The theme data to apply.
-  final DatePickerTheme theme;
-
-  /// The closest instance of this class that encloses the given context.
-  ///
-  /// If no such instance exists, returns an instance created by
-  /// [DefaultDatePickerTheme.fallback], which contains fallback values.
-  ///
-  /// Typical usage is as follows:
-  ///
-  /// ```dart
-  /// DefaultDatePickerTheme style = DefaultDatePickerTheme.of(context);
-  /// ```
-  static DefaultDatePickerTheme of(BuildContext context) {
-    return context.inheritFromWidgetOfExactType(DefaultDatePickerTheme) ?? const DefaultDatePickerTheme.fallback();
-  }
-
-  @override
-  bool updateShouldNotify(DefaultDatePickerTheme oldWidget) {
-    return theme != oldWidget.theme;
-  }
-
-  @override
-  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
-    super.debugFillProperties(properties);
-    theme?.debugFillProperties(properties);
-  }
 }

+ 13 - 0
lib/src/datetime_util.dart

@@ -0,0 +1,13 @@
+List<int> _leapYearMonths = const <int>[1, 3, 5, 7, 8, 10, 12];
+
+int calcDateCount(int year, int month) {
+  if (_leapYearMonths.contains(month)) {
+    return 31;
+  } else if (month == 2) {
+    if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
+      return 29;
+    }
+    return 28;
+  }
+  return 30;
+}

+ 1 - 2
pubspec.yaml

@@ -1,6 +1,6 @@
 name: flutter_datetime_picker
 description: A date time picker for flutter, you can choose date / time / date&time in English Dutch and Chinese, and you can also custom your own picker content
-version: 1.0.4
+version: 1.0.5
 author: Realank <realank@126.com>
 homepage: https://github.com/Realank/flutter_datetime_picker
 
@@ -10,7 +10,6 @@ environment:
 dependencies:
   flutter:
     sdk: flutter
-  flutter_commons_lang: ^1.0.5
 
 dev_dependencies:
   flutter_test: