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> {
// in the widget after first build is ignored.
DateTime initialDateTime;
// The currently selected values of the date picker.
int selectedDayFromInitial; // The difference in days between the initial date and the currently selected date.
// 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;
// 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 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.
FixedExtentScrollController amPmController;
// Estimated width of columns.
// The estimated width of columns.
final Map<int, double> estimatedColumnWidths = <int, double>{};
@override
......@@ -380,6 +399,8 @@ class _CupertinoDatePickerDateTimeState extends State<CupertinoDatePicker> {
amPmController = FixedExtentScrollController(initialItem: selectedAmPm);
}
previousHourIndex = selectedHour;
}
@override
......@@ -477,25 +498,29 @@ class _CupertinoDatePickerDateTimeState extends State<CupertinoDatePicker> {
if (widget.use24hFormat) {
selectedHour = index;
widget.onDateTimeChanged(_getDateTime());
}
else {
final int currentHourIn24h = selectedHour + selectedAmPm * 12;
} else {
selectedHour = index % 12;
// Automatically scrolls the am/pm column when the hour column value
// goes far enough. This behavior is similar to
// iOS picker version.
if (currentHourIn24h ~/ 12 != index ~/ 12) {
selectedHour = index % 12;
// goes far enough.
final bool wasAm = previousHourIndex >=0 && previousHourIndex <= 11;
final bool isAm = index >= 0 && index <= 11;
if (wasAm != isAm) {
// Animation values obtained by comparing with iOS version.
amPmController.animateToItem(
1 - amPmController.selectedItem,
duration: const Duration(milliseconds: 300), // Set by comparing with iOS version.
duration: const Duration(milliseconds: 300),
curve: Curves.easeOut,
); // Set by comparing with iOS version.
);
}
else {
selectedHour = index % 12;
widget.onDateTimeChanged(_getDateTime());
}
}
previousHourIndex = index;
},
children: List<Widget>.generate(24, (int index) {
int hour = index;
......
......@@ -7,6 +7,9 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/semantics.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() {
group('Countdown timer picker', () {
testWidgets('onTimerDurationChanged is not null', (WidgetTester tester) async {
......@@ -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 {
DateTime date;
await tester.pumpWidget(
......@@ -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(const Duration(milliseconds: 500));
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(const Duration(milliseconds: 500));
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(const Duration(milliseconds: 500));
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(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