Commit a872514a authored by Marco Scannadinari's avatar Marco Scannadinari Committed by xster

Fix immediately overriding the user's chosen AM/PM selection (#26904)

parent 6bb4b126
...@@ -351,16 +351,35 @@ class _CupertinoDatePickerDateTimeState extends State<CupertinoDatePicker> { ...@@ -351,16 +351,35 @@ class _CupertinoDatePickerDateTimeState extends State<CupertinoDatePicker> {
// in the widget after first build is ignored. // in the widget after first build is ignored.
DateTime initialDateTime; DateTime initialDateTime;
// The currently selected values of the date picker. // The difference in days between the initial date and the currently selected date.
int selectedDayFromInitial; // The difference in days between the initial date and the currently selected date. int selectedDayFromInitial;
// The current selection of the hour picker.
//
// If [widget.use24hFormat] is true, values range from 1-24. Otherwise values
// range from 1-12.
int selectedHour; int selectedHour;
// The previous selection index of the hour column.
//
// This ranges from 0-23 even if [widget.use24hFormat] is false. As a result,
// it can be used for determining if we just changed from AM -> PM or vice
// versa.
int previousHourIndex;
// The current selection of the minute picker. Values range from 0 to 59.
int selectedMinute; int selectedMinute;
int selectedAmPm; // 0 means AM, 1 means PM.
// The current selection of the AM/PM picker.
//
// - 0 means AM
// - 1 means PM
int selectedAmPm;
// The controller of the AM/PM column. // The controller of the AM/PM column.
FixedExtentScrollController amPmController; FixedExtentScrollController amPmController;
// Estimated width of columns. // The estimated width of columns.
final Map<int, double> estimatedColumnWidths = <int, double>{}; final Map<int, double> estimatedColumnWidths = <int, double>{};
@override @override
...@@ -380,6 +399,8 @@ class _CupertinoDatePickerDateTimeState extends State<CupertinoDatePicker> { ...@@ -380,6 +399,8 @@ class _CupertinoDatePickerDateTimeState extends State<CupertinoDatePicker> {
amPmController = FixedExtentScrollController(initialItem: selectedAmPm); amPmController = FixedExtentScrollController(initialItem: selectedAmPm);
} }
previousHourIndex = selectedHour;
} }
@override @override
...@@ -477,25 +498,29 @@ class _CupertinoDatePickerDateTimeState extends State<CupertinoDatePicker> { ...@@ -477,25 +498,29 @@ class _CupertinoDatePickerDateTimeState extends State<CupertinoDatePicker> {
if (widget.use24hFormat) { if (widget.use24hFormat) {
selectedHour = index; selectedHour = index;
widget.onDateTimeChanged(_getDateTime()); widget.onDateTimeChanged(_getDateTime());
} } else {
else { selectedHour = index % 12;
final int currentHourIn24h = selectedHour + selectedAmPm * 12;
// Automatically scrolls the am/pm column when the hour column value // Automatically scrolls the am/pm column when the hour column value
// goes far enough. This behavior is similar to // goes far enough.
// iOS picker version.
if (currentHourIn24h ~/ 12 != index ~/ 12) { final bool wasAm = previousHourIndex >=0 && previousHourIndex <= 11;
selectedHour = index % 12; final bool isAm = index >= 0 && index <= 11;
if (wasAm != isAm) {
// Animation values obtained by comparing with iOS version.
amPmController.animateToItem( amPmController.animateToItem(
1 - amPmController.selectedItem, 1 - amPmController.selectedItem,
duration: const Duration(milliseconds: 300), // Set by comparing with iOS version. duration: const Duration(milliseconds: 300),
curve: Curves.easeOut, curve: Curves.easeOut,
); // Set by comparing with iOS version. );
} }
else { else {
selectedHour = index % 12;
widget.onDateTimeChanged(_getDateTime()); widget.onDateTimeChanged(_getDateTime());
} }
} }
previousHourIndex = index;
}, },
children: List<Widget>.generate(24, (int index) { children: List<Widget>.generate(24, (int index) {
int hour = index; int hour = index;
......
...@@ -7,6 +7,9 @@ import 'package:flutter/cupertino.dart'; ...@@ -7,6 +7,9 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/semantics.dart'; import 'package:flutter/semantics.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
// scrolling by this offset will move the picker to the next item
const Offset _kRowOffset = Offset(0.0, -32.0);
void main() { void main() {
group('Countdown timer picker', () { group('Countdown timer picker', () {
testWidgets('onTimerDurationChanged is not null', (WidgetTester tester) async { testWidgets('onTimerDurationChanged is not null', (WidgetTester tester) async {
...@@ -524,6 +527,53 @@ void main() { ...@@ -524,6 +527,53 @@ void main() {
); );
}); });
testWidgets('picker persists am/pm value when scrolling hours', (WidgetTester tester) async {
DateTime date;
await tester.pumpWidget(
CupertinoApp(
home: SizedBox(
height: 400.0,
width: 400.0,
child: CupertinoDatePicker(
mode: CupertinoDatePickerMode.time,
onDateTimeChanged: (DateTime newDate) {
date = newDate;
},
initialDateTime: DateTime(2019, 1, 1, 3),
),
),
),
);
// 3:00 -> 15:00
await tester.drag(find.text('AM'), _kRowOffset);
await tester.pump();
await tester.pump(const Duration(milliseconds: 500));
expect(date, DateTime(2019, 1, 1, 15));
// 15:00 -> 16:00
await tester.drag(find.text('3'), _kRowOffset);
await tester.pump();
await tester.pump(const Duration(milliseconds: 500));
expect(date, DateTime(2019, 1, 1, 16));
// 16:00 -> 4:00
await tester.drag(find.text('PM'), -_kRowOffset);
await tester.pump();
await tester.pump(const Duration(milliseconds: 500));
expect(date, DateTime(2019, 1, 1, 4));
// 4:00 -> 3:00
await tester.drag(find.text('4'), -_kRowOffset);
await tester.pump();
await tester.pump(const Duration(milliseconds: 500));
expect(date, DateTime(2019, 1, 1, 3));
});
testWidgets('picker automatically scrolls the am/pm column when the hour column changes enough', (WidgetTester tester) async { testWidgets('picker automatically scrolls the am/pm column when the hour column changes enough', (WidgetTester tester) async {
DateTime date; DateTime date;
await tester.pumpWidget( await tester.pumpWidget(
...@@ -542,25 +592,29 @@ void main() { ...@@ -542,25 +592,29 @@ void main() {
), ),
); );
await tester.drag(find.text('11'), const Offset(0.0, -32.0)); // 11:59 -> 12:59
await tester.drag(find.text('11'), _kRowOffset);
await tester.pump(); await tester.pump();
await tester.pump(const Duration(milliseconds: 500)); await tester.pump(const Duration(milliseconds: 500));
expect(date, DateTime(2018, 1, 1, 12, 59)); expect(date, DateTime(2018, 1, 1, 12, 59));
await tester.drag(find.text('12'), const Offset(0.0, 32.0)); // 12:59 -> 11:59
await tester.drag(find.text('12'), -_kRowOffset);
await tester.pump(); await tester.pump();
await tester.pump(const Duration(milliseconds: 500)); await tester.pump(const Duration(milliseconds: 500));
expect(date, DateTime(2018, 1, 1, 11, 59)); expect(date, DateTime(2018, 1, 1, 11, 59));
await tester.drag(find.text('11'), const Offset(0.0, 64.0)); // 11:59 -> 9:59
await tester.drag(find.text('11'), -_kRowOffset * 2);
await tester.pump(); await tester.pump();
await tester.pump(const Duration(milliseconds: 500)); await tester.pump(const Duration(milliseconds: 500));
expect(date, DateTime(2018, 1, 1, 9, 59)); expect(date, DateTime(2018, 1, 1, 9, 59));
await tester.drag(find.text('9'), const Offset(0.0, -192.0)); // 9:59 -> 15:59
await tester.drag(find.text('9'), _kRowOffset * 6);
await tester.pump(); await tester.pump();
await tester.pump(const Duration(milliseconds: 500)); await tester.pump(const Duration(milliseconds: 500));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment