Force DatePicker value to stay within firstDate and lastDate upon year change (#26239)

* Force DatePicker value to stay within firstDate and lastDate upon year change

* updated per review feedback
This commit is contained in:
Hans Muller 2019-01-08 14:17:46 -08:00 committed by GitHub
parent 985ccb6d14
commit c8f72ac596
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 47 additions and 1 deletions

View file

@ -902,6 +902,13 @@ class _DatePickerDialogState extends State<_DatePickerDialog> {
}
void _handleYearChanged(DateTime value) {
if (value.isBefore(widget.firstDate))
value = widget.firstDate;
else if (value.isAfter(widget.lastDate))
value = widget.lastDate;
if (value == _selectedDate)
return;
_vibrate();
setState(() {
_mode = DatePickerMode.day;
@ -1067,9 +1074,12 @@ typedef SelectableDayPredicate = bool Function(DateTime day);
/// provided by [Directionality]. If both [locale] and [textDirection] are not
/// null, [textDirection] overrides the direction chosen for the [locale].
///
/// The `context` argument is passed to [showDialog], the documentation for
/// The [context] argument is passed to [showDialog], the documentation for
/// which discusses how it is used.
///
/// The [context], [initialDate], [firstDate], and [lastDate] parameters must
/// not be null.
///
/// See also:
///
/// * [showTimePicker], which shows a dialog that contains a material design
@ -1090,6 +1100,9 @@ Future<DateTime> showDatePicker({
Locale locale,
TextDirection textDirection,
}) async {
assert(initialDate != null);
assert(firstDate != null);
assert(lastDate != null);
assert(!initialDate.isBefore(firstDate), 'initialDate must be on or after firstDate');
assert(!initialDate.isAfter(lastDate), 'initialDate must be on or before lastDate');
assert(!firstDate.isAfter(lastDate), 'lastDate must be on or after firstDate');

View file

@ -279,6 +279,39 @@ void _tests() {
});
});
testWidgets('Selecting firstDate year respects firstDate', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/17309
initialDate = DateTime(2018, DateTime.may, 4);
firstDate = DateTime(2016, DateTime.june, 9);
lastDate = DateTime(2019, DateTime.january, 15);
await preparePicker(tester, (Future<DateTime> date) async {
await tester.tap(find.text('2018'));
await tester.pumpAndSettle();
await tester.tap(find.text('2016'));
await tester.pumpAndSettle();
await tester.tap(find.text('OK'));
await tester.pumpAndSettle();
expect(await date, DateTime(2016, DateTime.june, 9));
});
});
testWidgets('Selecting lastDate year respects lastDate', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/17309
initialDate = DateTime(2018, DateTime.may, 4);
firstDate = DateTime(2016, DateTime.june, 9);
lastDate = DateTime(2019, DateTime.january, 15);
await preparePicker(tester, (Future<DateTime> date) async {
await tester.tap(find.text('2018'));
await tester.pumpAndSettle();
await tester.tap(find.text('2019'));
await tester.pumpAndSettle();
await tester.tap(find.text('OK'));
await tester.pumpAndSettle();
expect(await date, DateTime(2019, DateTime.january, 15));
});
});
testWidgets('Only predicate days are selectable', (WidgetTester tester) async {
initialDate = DateTime(2017, DateTime.january, 16);
firstDate = DateTime(2017, DateTime.january, 10);