From 015da0a728ed2a3bb4fd28a357f0ad8043c5a1a5 Mon Sep 17 00:00:00 2001 From: James McIntosh Date: Sat, 7 Sep 2019 01:17:41 +1200 Subject: [PATCH 1/3] AMPM --- example/lib/date_picker_bottom_sheet.dart | 9 +- example/lib/datetime_picker_bottom_sheet.dart | 9 +- lib/src/date_time_formatter.dart | 31 ++- lib/src/widget/date_picker_widget.dart | 28 +-- lib/src/widget/datetime_picker_widget.dart | 183 +++++++++++++----- lib/src/widget/time_picker_widget.dart | 139 +++++++++---- 6 files changed, 278 insertions(+), 121 deletions(-) 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..a29a2ad 100644 --- a/lib/src/date_time_formatter.dart +++ b/lib/src/date_time_formatter.dart @@ -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( - int value, String format, DateTimePickerLocale locale) { + 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) { @@ -205,10 +219,19 @@ class DateTimeFormatter { /// format second text static String _formatSecond( - int value, String format, DateTimePickerLocale locale) { + int value, String format, DateTimePickerLocale locale) { 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 33f44b7..0eb0fcc 100644 --- a/lib/src/widget/datetime_picker_widget.dart +++ b/lib/src/widget/datetime_picker_widget.dart @@ -46,12 +46,14 @@ class DateTimePickerWidget extends StatefulWidget { class _DateTimePickerWidgetState extends State { DateTime _minTime, _maxTime; - int _currDay, _currHour, _currMinute, _currSecond; - List _dayRange, _hourRange, _minuteRange, _secondRange; + int _currDay, _currHour, _currMinute, _currSecond, _currAmpm; + List _dayRange, _12HourRange, _24HourRange, _minuteRange, _secondRange, _ampmRange; FixedExtentScrollController _dayScrollCtrl, - _hourScrollCtrl, + _12HourScrollCtrl, + _24HourScrollCtrl, _minuteScrollCtrl, - _secondScrollCtrl; + _secondScrollCtrl, + _ampmScrollCtrl; Map _scrollCtrlMap; Map> _valueRangeMap; @@ -94,8 +96,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(); @@ -107,22 +110,31 @@ 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); _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': _hourRange, 'm': _minuteRange, 's': _secondRange}; + _valueRangeMap = {'H': _24HourRange, 'h': _12HourRange, 'm': _minuteRange, 's': _secondRange, 'a': _ampmRange}; } @override @@ -181,29 +193,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); @@ -226,26 +230,31 @@ 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, 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); }); + pickers.addAll(timePickers); + return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: pickers); } @@ -318,8 +327,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(); @@ -327,6 +336,16 @@ class _DateTimePickerWidgetState 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 month picker void _changeMinuteSelection(int index) { int value = _minuteRange.first + index; @@ -346,19 +365,39 @@ class _DateTimePickerWidgetState extends State { } } - /// change range of minute and second + /// change the selection of ampm picker + void _changeAmPmSelection(int index) { + int value = _secondRange.first + index; + if (_currSecond != value) { + _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(); @@ -377,12 +416,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; }); @@ -390,9 +439,16 @@ 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); + } } } @@ -419,10 +475,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 @@ -433,7 +490,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; @@ -487,4 +565,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 1791894..b8498a3 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,29 @@ 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': _hourRange, 'm': _minuteRange, 's': _secondRange}; + _valueRangeMap = {'H': _24HourRange, 'h': _12HourRange, 'm': _minuteRange, 's': _secondRange, 'a': _ampmRange}; } @override @@ -168,51 +180,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 +231,9 @@ class _TimePickerWidgetState extends State { @required ValueChanged valueChanged, int minuteDivider = 1, }) { + int count = format.contains('m') + ? _calculateMinuteChildCount(valueRange, minuteDivider) + : valueRange.last - valueRange.first + 1; return Expanded( flex: 1, child: Container( @@ -235,9 +245,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 +282,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,6 +291,16 @@ 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 month picker void _changeMinuteSelection(int index) { int value = index * _minuteDivider; @@ -302,6 +320,15 @@ class _TimePickerWidgetState extends State { } } + /// change the selection of ampm picker + void _changeAmPmSelection(int index) { + int value = _secondRange.first + index; + if (_currSecond != value) { + _currHour = _currHour % 12 + index * 12; + _onSelectedChange(); + } + } + /// change range of minute and second void _changeTimeRange() { if (_isChangeTimeRange) { @@ -357,14 +384,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]; } @@ -413,4 +462,14 @@ 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 ]; + } + } From 521ca935811846814d3045bf768012449d067917 Mon Sep 17 00:00:00 2001 From: Tomas Radvansky Date: Sun, 29 Sep 2019 20:16:07 +1300 Subject: [PATCH 2/3] Fix AM/PM selection --- lib/src/widget/datetime_picker_widget.dart | 3 --- lib/src/widget/time_picker_widget.dart | 3 --- 2 files changed, 6 deletions(-) diff --git a/lib/src/widget/datetime_picker_widget.dart b/lib/src/widget/datetime_picker_widget.dart index 89ef18a..9a7dba5 100644 --- a/lib/src/widget/datetime_picker_widget.dart +++ b/lib/src/widget/datetime_picker_widget.dart @@ -409,11 +409,8 @@ class _DateTimePickerWidgetState extends State { /// change the selection of ampm picker void _changeAmPmSelection(int index) { - int value = _secondRange.first + index; - if (_currSecond != value) { _currHour = _currHour % 12 + index * 12; _onSelectedChange(); - } } /// change range of hour, minute, second and ampm diff --git a/lib/src/widget/time_picker_widget.dart b/lib/src/widget/time_picker_widget.dart index a47b0b2..808e83c 100644 --- a/lib/src/widget/time_picker_widget.dart +++ b/lib/src/widget/time_picker_widget.dart @@ -324,11 +324,8 @@ class _TimePickerWidgetState extends State { /// change the selection of ampm picker void _changeAmPmSelection(int index) { - int value = _secondRange.first + index; - if (_currSecond != value) { _currHour = _currHour % 12 + index * 12; _onSelectedChange(); - } } /// change range of minute and second From 4cf165c36e66be5d0c029b9557381fb331282ea4 Mon Sep 17 00:00:00 2001 From: Tomas Radvansky Date: Wed, 17 Jun 2020 10:15:53 +1200 Subject: [PATCH 3/3] Fixed merge issue, add AM/PM to example --- example/ios/Runner.xcodeproj/project.pbxproj | 20 +------------------- example/lib/time_picker_bottom_sheet.dart | 2 +- lib/src/widget/datetime_picker_widget.dart | 17 ++--------------- 3 files changed, 4 insertions(+), 35 deletions(-) diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index 0b6c87e..217f0f7 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -8,12 +8,7 @@ /* Begin PBXBuildFile section */ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; - 2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */ = {isa = PBXBuildFile; fileRef = 2D5378251FAA1A9400D5DBA9 /* flutter_assets */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; - 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; }; - 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; }; - 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; }; 9740EEB51CF90195004384FC /* Generated.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB31CF90195004384FC /* Generated.xcconfig */; }; 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; }; @@ -30,8 +25,6 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( - 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */, - 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -41,15 +34,12 @@ /* Begin PBXFileReference section */ 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; - 2D5378251FAA1A9400D5DBA9 /* flutter_assets */ = {isa = PBXFileReference; lastKnownFileType = folder; name = flutter_assets; path = Flutter/flutter_assets; sourceTree = SOURCE_ROOT; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; - 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; - 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; @@ -63,8 +53,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */, - 3B80C3941E831B6300D905FE /* App.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -74,10 +62,7 @@ 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( - 2D5378251FAA1A9400D5DBA9 /* flutter_assets */, - 3B80C3931E831B6300D905FE /* App.framework */, 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, - 9740EEBA1CF902C7004384FC /* Flutter.framework */, 9740EEB21CF90195004384FC /* Debug.xcconfig */, 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 9740EEB31CF90195004384FC /* Generated.xcconfig */, @@ -192,7 +177,6 @@ 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */, 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, - 2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */, 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -212,7 +196,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin"; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; @@ -265,7 +249,6 @@ /* Begin XCBuildConfiguration section */ 97C147031CF9000F007C117D /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; @@ -319,7 +302,6 @@ }; 97C147041CF9000F007C117D /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; diff --git a/example/lib/time_picker_bottom_sheet.dart b/example/lib/time_picker_bottom_sheet.dart index 4f81dfa..b28e6f8 100644 --- a/example/lib/time_picker_bottom_sheet.dart +++ b/example/lib/time_picker_bottom_sheet.dart @@ -14,7 +14,7 @@ const String MAX_DATETIME = '2021-11-25 22:45:10'; const String INIT_DATETIME = '2019-05-17 18:13:15'; class _TimePickerBottomSheetState extends State { - String _format = 'HH:mm'; + String _format = 'hh:mm a'; TextEditingController _formatCtrl = TextEditingController(); DateTime _dateTime; diff --git a/lib/src/widget/datetime_picker_widget.dart b/lib/src/widget/datetime_picker_widget.dart index 204f436..23d96a7 100644 --- a/lib/src/widget/datetime_picker_widget.dart +++ b/lib/src/widget/datetime_picker_widget.dart @@ -314,19 +314,6 @@ class _DateTimePickerWidgetState extends State { childCount: format.contains('m') ? _calculateMinuteChildCount(valueRange, minuteDivider) : valueRange.last - valueRange.first + 1, - itemBuilder: itemBuilder == null - ? (context, index) { - int value = valueRange.first + index; - - if (format.contains('m')) { - value = minuteDivider * index; - } - - return _renderDatePickerItemComponent(value, format); - } - : itemBuilder, - ? _calculateMinuteChildCount(valueRange, minuteDivider) - : valueRange.last - valueRange.first + 1, itemBuilder: builder, ), ); @@ -424,8 +411,8 @@ class _DateTimePickerWidgetState extends State { /// change the selection of ampm picker void _changeAmPmSelection(int index) { - _currHour = _currHour % 12 + index * 12; - _onSelectedChange(); + _currHour = _currHour % 12 + index * 12; + _onSelectedChange(); } /// change range of hour, minute, second and ampm