diff --git a/example/lib/date_picker_bottom_sheet.dart b/example/lib/date_picker_bottom_sheet.dart index eaf9333..bae72c0 100644 --- a/example/lib/date_picker_bottom_sheet.dart +++ b/example/lib/date_picker_bottom_sheet.dart @@ -34,9 +34,8 @@ class _DatePickerBottomSheetState extends State { @override Widget build(BuildContext context) { // create locale radio list - List radios = List(); - _locales.forEach((locale) { - radios.add(Container( + List radios = _locales.map((locale) { + return Container( margin: EdgeInsets.only(right: 8.0), child: Row( mainAxisSize: MainAxisSize.min, @@ -55,8 +54,8 @@ class _DatePickerBottomSheetState extends State { .substring(locale.toString().indexOf('.') + 1)), ], ), - )); - }); + ); + }).toList(); TextStyle hintTextStyle = Theme.of(context).textTheme.subhead.apply(color: Color(0xFF999999)); diff --git a/example/lib/datetime_picker_bottom_sheet.dart b/example/lib/datetime_picker_bottom_sheet.dart index cdae579..e093fff 100644 --- a/example/lib/datetime_picker_bottom_sheet.dart +++ b/example/lib/datetime_picker_bottom_sheet.dart @@ -62,9 +62,8 @@ class _DateTimePickerBottomSheetState extends State { @override Widget build(BuildContext context) { - List radios = List(); - _locales.forEach((locale) { - radios.add(Container( + List radios = _locales.map((locale) { + return Container( margin: EdgeInsets.only(right: 8.0), child: Row( mainAxisSize: MainAxisSize.min, @@ -82,8 +81,8 @@ class _DateTimePickerBottomSheetState extends State { .substring(locale.toString().indexOf('.') + 1)), ], ), - )); - }); + ); + }).toList(); TextStyle hintTextStyle = Theme.of(context).textTheme.subhead.apply(color: Color(0xFF999999)); diff --git a/lib/src/date_time_formatter.dart b/lib/src/date_time_formatter.dart index 5357a52..bebcca6 100644 --- a/lib/src/date_time_formatter.dart +++ b/lib/src/date_time_formatter.dart @@ -24,14 +24,14 @@ class DateTimeFormatter { return ''; } - /// Check if the date format is for day(contain y、M、d、E) or not. + /// Check if the date format is for day(contain y, M, d, E) or not. static bool isDayFormat(String format) { return format.contains(RegExp(r'[yMdE]')); } - /// Check if the date format is for time(contain H、m、s) or not. + /// Check if the date format is for time(contain H, h, m, s, a) or not. static bool isTimeFormat(String format) { - return format.contains(RegExp(r'[Hms]')); + return format.contains(RegExp(r'[Hhmsa]')); } /// Split date format to array. @@ -97,8 +97,12 @@ class DateTimeFormatter { result = _formatWeek(value, result, locale); } // format hour text + if (format.contains('h')) { + result = _format12Hour(value, result, locale); + } + // format hour text if (format.contains('H')) { - result = _formatHour(value, result, locale); + result = _format24Hour(value, result, locale); } // format minute text if (format.contains('m')) { @@ -108,6 +112,10 @@ class DateTimeFormatter { if (format.contains('s')) { result = _formatSecond(value, result, locale); } + // format second text + if (format.contains('a')) { + result = _formatAmpm(value, result, locale); + } if (result == format) { return value.toString(); } @@ -192,11 +200,17 @@ class DateTimeFormatter { } /// format hour text - static String _formatHour( + static String _format24Hour( int value, String format, DateTimePickerLocale locale) { return _formatNumber(value, format, 'H'); } + /// format hour text + static String _format12Hour( + int value, String format, DateTimePickerLocale locale) { + return _formatNumber(value % 12 == 0 ? 12 : value % 12, format, 'h'); + } + /// format minute text static String _formatMinute( int value, String format, DateTimePickerLocale locale) { @@ -209,6 +223,15 @@ class DateTimeFormatter { return _formatNumber(value, format, 's'); } + /// format ampm text + static String _formatAmpm( + int value, String format, DateTimePickerLocale locale) { + if (value == 0) { + return 'AM'; + } + return 'PM'; + } + /// format number, if the digit count is 2, will pad zero on the left static String _formatNumber(int value, String format, String unit) { if (format.contains('$unit$unit')) { diff --git a/lib/src/widget/date_picker_widget.dart b/lib/src/widget/date_picker_widget.dart index cf8bc1c..6bb4c27 100644 --- a/lib/src/widget/date_picker_widget.dart +++ b/lib/src/widget/date_picker_widget.dart @@ -150,35 +150,26 @@ class _DatePickerWidgetState extends State { /// find scroll controller by specified format FixedExtentScrollController _findScrollCtrl(String format) { - FixedExtentScrollController scrollCtrl; - _scrollCtrlMap.forEach((key, value) { - if (format.contains(key)) { - scrollCtrl = value; - } - }); - return scrollCtrl; + String key = _scrollCtrlMap.keys.firstWhere((key) => format.contains(key)); + + return _scrollCtrlMap[key]; } /// find item value range by specified format List _findPickerItemRange(String format) { - List valueRange; - _valueRangeMap.forEach((key, value) { - if (format.contains(key)) { - valueRange = value; - } - }); - return valueRange; + String key = _valueRangeMap.keys.firstWhere((key) => format.contains(key)); + + return _valueRangeMap[key]; } /// render the picker widget of year、month and day Widget _renderDatePickerWidget() { - List pickers = List(); List formatArr = DateTimeFormatter.splitDateFormat(widget.dateFormat); - formatArr.forEach((format) { + List pickers = formatArr.map((format) { List valueRange = _findPickerItemRange(format); - Widget pickerColumn = _renderDatePickerColumnComponent( + return _renderDatePickerColumnComponent( scrollCtrl: _findScrollCtrl(format), valueRange: valueRange, format: format, @@ -192,8 +183,7 @@ class _DatePickerWidgetState extends State { } }, ); - pickers.add(pickerColumn); - }); + }).toList(); return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: pickers); } diff --git a/lib/src/widget/datetime_picker_widget.dart b/lib/src/widget/datetime_picker_widget.dart index b7d983e..5eeffc3 100644 --- a/lib/src/widget/datetime_picker_widget.dart +++ b/lib/src/widget/datetime_picker_widget.dart @@ -43,18 +43,28 @@ class DateTimePickerWidget extends StatefulWidget { @override State createState() => _DateTimePickerWidgetState( - this.minDateTime, this.maxDateTime, this.initDateTime, this.minuteDivider); + this.minDateTime, + this.maxDateTime, + this.initDateTime, + this.minuteDivider); } class _DateTimePickerWidgetState extends State { DateTime _minTime, _maxTime; - int _currDay, _currHour, _currMinute, _currSecond; + int _currDay, _currHour, _currMinute, _currSecond, _currAmpm; int _minuteDivider; - List _dayRange, _hourRange, _minuteRange, _secondRange; + List _dayRange, + _12HourRange, + _24HourRange, + _minuteRange, + _secondRange, + _ampmRange; FixedExtentScrollController _dayScrollCtrl, - _hourScrollCtrl, + _12HourScrollCtrl, + _24HourScrollCtrl, _minuteScrollCtrl, - _secondScrollCtrl; + _secondScrollCtrl, + _ampmScrollCtrl; Map _scrollCtrlMap; Map> _valueRangeMap; @@ -63,8 +73,8 @@ class _DateTimePickerWidgetState extends State { final DateTime _baselineDate = DateTime(1900, 1, 1); - _DateTimePickerWidgetState( - DateTime minTime, DateTime maxTime, DateTime initTime, int minuteDivider) { + _DateTimePickerWidgetState(DateTime minTime, DateTime maxTime, + DateTime initTime, int minuteDivider) { // check minTime value if (minTime == null) { minTime = DateTime.parse(DATE_PICKER_MIN_DATETIME); @@ -99,8 +109,9 @@ class _DateTimePickerWidgetState extends State { this._currDay = min(max(_dayRange.first, currDate), _dayRange.last); // limit the range of hour - this._hourRange = _calcHourRange(); - this._currHour = min(max(_hourRange.first, _currHour), _hourRange.last); + this._12HourRange = _calc12HourRange(); + this._24HourRange = _calc24HourRange(); + this._currHour = min(max(_24HourRange.first, _currHour), _24HourRange.last); // limit the range of minute this._minuteRange = _calcMinuteRange(); @@ -112,22 +123,38 @@ class _DateTimePickerWidgetState extends State { this._currSecond = min(max(_secondRange.first, _currSecond), _secondRange.last); + this._ampmRange = _calcAmpmRange(); + this._currAmpm = _currHour < 12 ? 0 : 1; + // create scroll controller _dayScrollCtrl = FixedExtentScrollController(initialItem: _currDay - _dayRange.first); - _hourScrollCtrl = - FixedExtentScrollController(initialItem: _currHour - _hourRange.first); + _24HourScrollCtrl = FixedExtentScrollController( + initialItem: _currHour - _24HourRange.first); + _12HourScrollCtrl = FixedExtentScrollController( + initialItem: + (_currHour % 12 == 0 ? 12 : _currHour % 12) - _12HourRange.first); _minuteScrollCtrl = FixedExtentScrollController( initialItem: (_currMinute - _minuteRange.first) ~/ _minuteDivider); _secondScrollCtrl = FixedExtentScrollController( initialItem: _currSecond - _secondRange.first); + _ampmScrollCtrl = + FixedExtentScrollController(initialItem: (_currHour / 12).floor()); _scrollCtrlMap = { - 'H': _hourScrollCtrl, + 'H': _24HourScrollCtrl, + 'h': _12HourScrollCtrl, 'm': _minuteScrollCtrl, - 's': _secondScrollCtrl + 's': _secondScrollCtrl, + 'a': _ampmScrollCtrl, + }; + _valueRangeMap = { + 'H': _24HourRange, + 'h': _12HourRange, + 'm': _minuteRange, + 's': _secondRange, + 'a': _ampmRange }; - _valueRangeMap = {'H': _hourRange, 'm': _minuteRange, 's': _secondRange}; } @override @@ -186,29 +213,21 @@ class _DateTimePickerWidgetState extends State { /// find scroll controller by specified format FixedExtentScrollController _findScrollCtrl(String format) { - FixedExtentScrollController scrollCtrl; - _scrollCtrlMap.forEach((key, value) { - if (format.contains(key)) { - scrollCtrl = value; - } - }); - return scrollCtrl; + String key = _scrollCtrlMap.keys.firstWhere((key) => format.contains(key)); + + return _scrollCtrlMap[key]; } /// find item value range by specified format List _findPickerItemRange(String format) { - List valueRange; - _valueRangeMap.forEach((key, value) { - if (format.contains(key)) { - valueRange = value; - } - }); - return valueRange; + String key = _valueRangeMap.keys.firstWhere((key) => format.contains(key)); + + return _valueRangeMap[key]; } /// render the picker widget of year、month and day Widget _renderDatePickerWidget() { - List pickers = List(); + List pickers = []; List formatArr = DateTimeFormatter.splitDateFormat( widget.dateFormat, mode: DateTimePickerMode.datetime); @@ -231,27 +250,32 @@ class _DateTimePickerWidgetState extends State { pickers.add(dayPickerColumn); // render time picker column - formatArr.forEach((format) { + List timePickers = formatArr.map((format) { List valueRange = _findPickerItemRange(format); - Widget pickerColumn = _renderDatePickerColumnComponent( + return _renderDatePickerColumnComponent( scrollCtrl: _findScrollCtrl(format), valueRange: valueRange, format: format, flex: 1, minuteDivider: widget.minuteDivider, valueChanged: (value) { - if (format.contains('H')) { - _changeHourSelection(value); + if (format.contains('h')) { + _change12HourSelection(value); + } else if (format.contains('H')) { + _change24HourSelection(value); } else if (format.contains('m')) { _changeMinuteSelection(value); } else if (format.contains('s')) { _changeSecondSelection(value); + } else if (format.contains('a')) { + _changeAmPmSelection(value); } }, ); - pickers.add(pickerColumn); - }); + }).toList(); + pickers.addAll(timePickers); + return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: pickers); } @@ -276,17 +300,18 @@ class _DateTimePickerWidgetState extends State { itemExtent: widget.pickerTheme.itemHeight, onSelectedItemChanged: valueChanged, childCount: format.contains('m') - ? _calculateMinuteChildCount(valueRange, minuteDivider) - : valueRange.last - valueRange.first + 1, - itemBuilder: (context, index) { - int value = valueRange.first + index; - - if (format.contains('m')) { - value = minuteDivider * index; - } - - return _renderDatePickerItemComponent(value, format); - }, + ? _calculateMinuteChildCount(valueRange, minuteDivider) + : valueRange.last - valueRange.first + 1, + itemBuilder: itemBuilder ?? + (context, index) { + int value = valueRange.first + index; + + if (format.contains('m')) { + value = minuteDivider * index; + } + + return _renderDatePickerItemComponent(value, format); + }, ), ); return Expanded( @@ -342,8 +367,8 @@ class _DateTimePickerWidgetState extends State { } /// change the selection of hour picker - void _changeHourSelection(int index) { - int value = _hourRange.first + index; + void _change24HourSelection(int index) { + int value = _24HourRange.first + index; if (_currHour != value) { _currHour = value; _changeTimeRange(); @@ -352,8 +377,18 @@ class _DateTimePickerWidgetState extends State { } /// change the selection of minute picker + void _change12HourSelection(int index) { + int value = _12HourRange.first + index; + if (_currHour != value) { + _currHour = (value == 12 ? 0 : value) + 12 * _currAmpm; + _changeTimeRange(); + _onSelectedChange(); + } + } + + /// change the selection of month picker void _changeMinuteSelection(int index) { - // TODO: copied from time_picker_widget - this looks like it would break date ranges but not taking into account _minuteRange.first + // TODO: copied from time_picker_widget - this looks like it would break date ranges by not taking into account _minuteRange.first int value = index * _minuteDivider; // int value = _minuteRange.first + index; if (_currMinute != value) { @@ -372,19 +407,36 @@ class _DateTimePickerWidgetState extends State { } } - /// change range of minute and second + /// change the selection of ampm picker + void _changeAmPmSelection(int index) { + _currHour = _currHour % 12 + index * 12; + _onSelectedChange(); + } + + /// change range of hour, minute, second and ampm void _changeTimeRange() { if (_isChangeTimeRange) { return; } _isChangeTimeRange = true; - List hourRange = _calcHourRange(); - bool hourRangeChanged = _hourRange.first != hourRange.first || - _hourRange.last != hourRange.last; - if (hourRangeChanged) { - // selected day changed - _currHour = max(min(_currHour, hourRange.last), hourRange.first); + bool hourRangeChanged = false; + List hourRange12 = _calc12HourRange(); + List hourRange24 = _calc24HourRange(); + if (widget.dateFormat.contains('h')) { + hourRangeChanged = _12HourRange.first != hourRange12.first || + _12HourRange.last != hourRange12.last; + if (hourRangeChanged) { + // selected day changed + _currHour = max(min(_currHour, hourRange12.last), hourRange12.first); + } + } else { + hourRangeChanged = _24HourRange.first != hourRange24.first || + _24HourRange.last != hourRange24.last; + if (hourRangeChanged) { + // selected day changed + _currHour = max(min(_currHour, hourRange24.last), hourRange24.first); + } } List minuteRange = _calcMinuteRange(); @@ -403,12 +455,22 @@ class _DateTimePickerWidgetState extends State { _currSecond = max(min(_currSecond, secondRange.last), secondRange.first); } + List ampmRange = _calcAmpmRange(); + bool ampmRangeChanged = _ampmRange.first != ampmRange.first || + _ampmRange.last != ampmRange.last; + if (ampmRangeChanged) { + // ampm range changed, need limit the value of selected ampm + _currAmpm = max(min(_currAmpm, ampmRange.last), ampmRange.first); + } + setState(() { - _hourRange = hourRange; + _12HourRange = hourRange12; + _24HourRange = hourRange24; _minuteRange = minuteRange; _secondRange = secondRange; - _valueRangeMap['H'] = hourRange; + _valueRangeMap['h'] = hourRange12; + _valueRangeMap['H'] = hourRange24; _valueRangeMap['m'] = minuteRange; _valueRangeMap['s'] = secondRange; }); @@ -416,16 +478,24 @@ class _DateTimePickerWidgetState extends State { if (hourRangeChanged) { // CupertinoPicker refresh data not working (https://github.com/flutter/flutter/issues/22999) int currHour = _currHour; - _hourScrollCtrl.jumpToItem(hourRange.last - hourRange.first); - if (currHour < hourRange.last) { - _hourScrollCtrl.jumpToItem(currHour - hourRange.first); + if (widget.dateFormat.contains('h')) { + _12HourScrollCtrl.jumpToItem(hourRange12.last - hourRange12.first); + if (currHour < hourRange12.last) { + _12HourScrollCtrl.jumpToItem(currHour - hourRange12.first); + } + } else { + _24HourScrollCtrl.jumpToItem(hourRange24.last - hourRange24.first); + if (currHour < hourRange24.last) { + _24HourScrollCtrl.jumpToItem(currHour - hourRange24.first); + } } } if (minuteRangeChanged) { // CupertinoPicker refresh data not working (https://github.com/flutter/flutter/issues/22999) int currMinute = _currMinute; - _minuteScrollCtrl.jumpToItem((minuteRange.last - minuteRange.first) ~/ _minuteDivider); + _minuteScrollCtrl + .jumpToItem((minuteRange.last - minuteRange.first) ~/ _minuteDivider); if (currMinute < minuteRange.last) { _minuteScrollCtrl.jumpToItem(currMinute - minuteRange.first); } @@ -445,10 +515,11 @@ class _DateTimePickerWidgetState extends State { /// calculate selected index list List _calcSelectIndexList() { - int hourIndex = _currHour - _hourRange.first; + int hourIndex = _currHour - _24HourRange.first; int minuteIndex = _currMinute - _minuteRange.first; int secondIndex = _currSecond - _secondRange.first; - return [hourIndex, minuteIndex, secondIndex]; + int ampmIndex = _currAmpm; + return [hourIndex, minuteIndex, secondIndex, ampmIndex]; } /// calculate the range of day @@ -459,7 +530,28 @@ class _DateTimePickerWidgetState extends State { } /// calculate the range of hour - List _calcHourRange() { + List _calc12HourRange() { + int minHour = 1, maxHour = 12; + if (_currAmpm == 0) { + if (_currDay == _dayRange.first && _minTime.hour < 12) { + minHour = _minTime.hour; + } + if (_currDay == _dayRange.last && _maxTime.hour < 12) { + maxHour = _maxTime.hour; + } + } else if (_currAmpm == 1) { + if (_currDay == _dayRange.first && _minTime.hour >= 12) { + minHour = _minTime.hour; + } + if (_currDay == _dayRange.last && _maxTime.hour >= 12) { + maxHour = _maxTime.hour; + } + } + return [minHour, maxHour]; + } + + /// calculate the range of hour + List _calc24HourRange() { int minHour = 0, maxHour = 23; if (_currDay == _dayRange.first) { minHour = _minTime.hour; @@ -513,4 +605,13 @@ class _DateTimePickerWidgetState extends State { } return [minSecond, maxSecond]; } + + List _calcAmpmRange({currHour, currMinute}) { + if (_24HourRange.first < 12 && _24HourRange.last > 12) { + return [0, 1]; + } else if (_24HourRange.first < 12) { + return [0]; + } + return [1]; + } } diff --git a/lib/src/widget/time_picker_widget.dart b/lib/src/widget/time_picker_widget.dart index 4d1898e..60d63b1 100644 --- a/lib/src/widget/time_picker_widget.dart +++ b/lib/src/widget/time_picker_widget.dart @@ -50,12 +50,14 @@ class TimePickerWidget extends StatefulWidget { class _TimePickerWidgetState extends State { DateTime _minTime, _maxTime; - int _currHour, _currMinute, _currSecond; + int _currHour, _currMinute, _currSecond, _currAmpm; int _minuteDivider; - List _hourRange, _minuteRange, _secondRange; - FixedExtentScrollController _hourScrollCtrl, + List _12HourRange, _24HourRange, _minuteRange, _secondRange, _ampmRange; + FixedExtentScrollController _12HourScrollCtrl, + _24HourScrollCtrl, _minuteScrollCtrl, - _secondScrollCtrl; + _secondScrollCtrl, + _ampmScrollCtrl; Map _scrollCtrlMap; Map> _valueRangeMap; @@ -83,8 +85,9 @@ class _TimePickerWidgetState extends State { this._minuteDivider = minuteDivider; // limit the range of hour - this._hourRange = _calcHourRange(); - this._currHour = min(max(_hourRange.first, _currHour), _hourRange.last); + this._12HourRange = _calc12HourRange(); + this._24HourRange = _calc24HourRange(); + this._currHour = min(max(_24HourRange.first, _currHour), _24HourRange.last); // limit the range of minute this._minuteRange = _calcMinuteRange(); @@ -96,20 +99,36 @@ class _TimePickerWidgetState extends State { this._currSecond = min(max(_secondRange.first, _currSecond), _secondRange.last); + this._ampmRange = _calcAmpmRange(); + this._currAmpm = _currHour < 12 ? 0 : 1; + // create scroll controller - _hourScrollCtrl = - FixedExtentScrollController(initialItem: _currHour - _hourRange.first); + _24HourScrollCtrl = FixedExtentScrollController( + initialItem: _currHour - _24HourRange.first); + _12HourScrollCtrl = FixedExtentScrollController( + initialItem: + (_currHour % 12 == 0 ? 12 : _currHour % 12) - _12HourRange.first); _minuteScrollCtrl = FixedExtentScrollController( initialItem: (_currMinute - _minuteRange.first) ~/ _minuteDivider); _secondScrollCtrl = FixedExtentScrollController( initialItem: _currSecond - _secondRange.first); + _ampmScrollCtrl = + FixedExtentScrollController(initialItem: (_currHour / 12).floor()); _scrollCtrlMap = { - 'H': _hourScrollCtrl, + 'H': _24HourScrollCtrl, + 'h': _12HourScrollCtrl, 'm': _minuteScrollCtrl, - 's': _secondScrollCtrl + 's': _secondScrollCtrl, + 'a': _ampmScrollCtrl, + }; + _valueRangeMap = { + 'H': _24HourRange, + 'h': _12HourRange, + 'm': _minuteRange, + 's': _secondRange, + 'a': _ampmRange }; - _valueRangeMap = {'H': _hourRange, 'm': _minuteRange, 's': _secondRange}; } @override @@ -168,51 +187,46 @@ class _TimePickerWidgetState extends State { /// find scroll controller by specified format FixedExtentScrollController _findScrollCtrl(String format) { - FixedExtentScrollController scrollCtrl; - _scrollCtrlMap.forEach((key, value) { - if (format.contains(key)) { - scrollCtrl = value; - } - }); - return scrollCtrl; + String key = _scrollCtrlMap.keys.firstWhere((key) => format.contains(key)); + + return _scrollCtrlMap[key]; } /// find item value range by specified format List _findPickerItemRange(String format) { - List valueRange; - _valueRangeMap.forEach((key, value) { - if (format.contains(key)) { - valueRange = value; - } - }); - return valueRange; + String key = _valueRangeMap.keys.firstWhere((key) => format.contains(key)); + + return _valueRangeMap[key]; } /// render the picker widget of year、month and day Widget _renderDatePickerWidget() { - List pickers = List(); List formatArr = DateTimeFormatter.splitDateFormat(widget.dateFormat); - formatArr.forEach((format) { + + List pickers = formatArr.map((format) { List valueRange = _findPickerItemRange(format); - Widget pickerColumn = _renderDatePickerColumnComponent( + return _renderDatePickerColumnComponent( scrollCtrl: _findScrollCtrl(format), valueRange: valueRange, format: format, minuteDivider: widget.minuteDivider, valueChanged: (value) { - if (format.contains('H')) { - _changeHourSelection(value); + if (format.contains('h')) { + _change12HourSelection(value); + } else if (format.contains('H')) { + _change24HourSelection(value); } else if (format.contains('m')) { _changeMinuteSelection(value); } else if (format.contains('s')) { _changeSecondSelection(value); + } else if (format.contains('a')) { + _changeAmPmSelection(value); } }, ); - pickers.add(pickerColumn); - }); + }).toList(); return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: pickers); } @@ -224,6 +238,9 @@ class _TimePickerWidgetState extends State { @required ValueChanged valueChanged, int minuteDivider, }) { + int count = format.contains('m') + ? _calculateMinuteChildCount(valueRange, minuteDivider) + : valueRange.last - valueRange.first + 1; return Expanded( flex: 1, child: Container( @@ -235,9 +252,7 @@ class _TimePickerWidgetState extends State { scrollController: scrollCtrl, itemExtent: widget.pickerTheme.itemHeight, onSelectedItemChanged: valueChanged, - childCount: format.contains('m') - ? _calculateMinuteChildCount(valueRange, minuteDivider) - : valueRange.last - valueRange.first + 1, + childCount: count, itemBuilder: (context, index) { int value = valueRange.first + index; @@ -274,8 +289,8 @@ class _TimePickerWidgetState extends State { } /// change the selection of hour picker - void _changeHourSelection(int index) { - int value = _hourRange.first + index; + void _change24HourSelection(int index) { + int value = _24HourRange.first + index; if (_currHour != value) { _currHour = value; _changeTimeRange(); @@ -283,9 +298,19 @@ class _TimePickerWidgetState extends State { } } + /// change the selection of hour picker + void _change12HourSelection(int index) { + int value = _12HourRange.first + index; + if (_currHour != value) { + _currHour = (value == 12 ? 0 : value) + 12 * _currAmpm; + _changeTimeRange(); + _onSelectedChange(); + } + } + /// change the selection of minute picker void _changeMinuteSelection(int index) { - // TODO: this looks like it would break date ranges but not taking into account _minuteRange.first + // TODO: this looks like it would break date ranges by not taking into account _minuteRange.first int value = index * _minuteDivider; if (_currMinute != value) { _currMinute = value; @@ -303,6 +328,12 @@ class _TimePickerWidgetState extends State { } } + /// change the selection of ampm picker + void _changeAmPmSelection(int index) { + _currHour = _currHour % 12 + index * 12; + _onSelectedChange(); + } + /// change range of minute and second void _changeTimeRange() { if (_isChangeTimeRange) { @@ -358,14 +389,36 @@ class _TimePickerWidgetState extends State { /// calculate selected index list List _calcSelectIndexList() { - int hourIndex = _currHour - _hourRange.first; + int hourIndex = _currHour - _24HourRange.first; int minuteIndex = _currMinute - _minuteRange.first; int secondIndex = _currSecond - _secondRange.first; - return [hourIndex, minuteIndex, secondIndex]; + int ampmIndex = _currAmpm; + return [hourIndex, minuteIndex, secondIndex, ampmIndex]; } /// calculate the range of hour - List _calcHourRange() { + List _calc12HourRange() { + int minHour = 1, maxHour = 12; + if (_currAmpm == 0) { + if (_minTime.hour < 12) { + minHour = _minTime.hour; + } + if (_maxTime.hour < 12) { + maxHour = _maxTime.hour; + } + } else if (_currAmpm == 1) { + if (_minTime.hour >= 12) { + minHour = _minTime.hour; + } + if (_maxTime.hour >= 12) { + maxHour = _maxTime.hour; + } + } + return [minHour, maxHour]; + } + + /// calculate the range of hour + List _calc24HourRange() { return [_minTime.hour, _maxTime.hour]; } @@ -414,4 +467,13 @@ class _TimePickerWidgetState extends State { } return [minSecond, maxSecond]; } + + List _calcAmpmRange({currHour, currMinute}) { + if (_24HourRange.first < 12 && _24HourRange.last > 12) { + return [0, 1]; + } else if (_24HourRange.first < 12) { + return [0]; + } + return [1]; + } }