From e77cb1a06b35e82b184329d59adeb7beff073100 Mon Sep 17 00:00:00 2001 From: Mitchell Goodwin <58190796+MitchellGoodwin@users.noreply.github.com> Date: Fri, 10 Mar 2023 13:51:07 -0800 Subject: [PATCH] Constrain date picker to max width to avoid bending outwards (#120827) Constrain date picker to max width to avoid bending outwards --- .../lib/src/cupertino/date_picker.dart | 22 ++++++-- .../test/cupertino/date_picker_test.dart | 50 +++++++++++++++++++ 2 files changed, 69 insertions(+), 3 deletions(-) diff --git a/packages/flutter/lib/src/cupertino/date_picker.dart b/packages/flutter/lib/src/cupertino/date_picker.dart index 126002c4b5..515de78980 100644 --- a/packages/flutter/lib/src/cupertino/date_picker.dart +++ b/packages/flutter/lib/src/cupertino/date_picker.dart @@ -81,6 +81,7 @@ class _DatePickerLayoutDelegate extends MultiChildLayoutDelegate { _DatePickerLayoutDelegate({ required this.columnWidths, required this.textDirectionFactor, + required this.maxWidth, }); // The list containing widths of all columns. @@ -89,16 +90,19 @@ class _DatePickerLayoutDelegate extends MultiChildLayoutDelegate { // textDirectionFactor is 1 if text is written left to right, and -1 if right to left. final int textDirectionFactor; + // The max width the children should reach to avoid bending outwards. + final double maxWidth; + @override void performLayout(Size size) { - double remainingWidth = size.width; + double remainingWidth = maxWidth < size.width ? maxWidth : size.width; + + double currentHorizontalOffset = (size.width - remainingWidth) / 2; for (int i = 0; i < columnWidths.length; i++) { remainingWidth -= columnWidths[i] + _kDatePickerPadSize * 2; } - double currentHorizontalOffset = 0.0; - for (int i = 0; i < columnWidths.length; i++) { final int index = textDirectionFactor == 1 ? i : columnWidths.length - i - 1; @@ -1024,6 +1028,7 @@ class _CupertinoDatePickerDateTimeState extends State { } final List pickers = []; + double totalColumnWidths = 4 * _kDatePickerPadSize; for (int i = 0; i < columnWidths.length; i++) { double offAxisFraction = 0.0; @@ -1044,6 +1049,8 @@ class _CupertinoDatePickerDateTimeState extends State { padding = padding.flipped; } + totalColumnWidths += columnWidths[i] + (2 * _kDatePickerPadSize); + pickers.add(LayoutId( id: i, child: pickerBuilders[i]( @@ -1068,6 +1075,8 @@ class _CupertinoDatePickerDateTimeState extends State { )); } + final double maxPickerWidth = totalColumnWidths > _kPickerWidth ? totalColumnWidths : _kPickerWidth; + return MediaQuery( data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0), child: DefaultTextStyle.merge( @@ -1076,6 +1085,7 @@ class _CupertinoDatePickerDateTimeState extends State { delegate: _DatePickerLayoutDelegate( columnWidths: columnWidths, textDirectionFactor: textDirectionFactor, + maxWidth: maxPickerWidth, ), children: pickers, ), @@ -1418,6 +1428,7 @@ class _CupertinoDatePickerDateState extends State { } final List pickers = []; + double totalColumnWidths = 4 * _kDatePickerPadSize; for (int i = 0; i < columnWidths.length; i++) { final double offAxisFraction = (i - 1) * 0.3 * textDirectionFactor; @@ -1434,6 +1445,8 @@ class _CupertinoDatePickerDateState extends State { selectionOverlay = _endSelectionOverlay; } + totalColumnWidths += columnWidths[i] + (2 * _kDatePickerPadSize); + pickers.add(LayoutId( id: i, child: pickerBuilders[i]( @@ -1456,6 +1469,8 @@ class _CupertinoDatePickerDateState extends State { )); } + final double maxPickerWidth = totalColumnWidths > _kPickerWidth ? totalColumnWidths : _kPickerWidth; + return MediaQuery( data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0), child: DefaultTextStyle.merge( @@ -1464,6 +1479,7 @@ class _CupertinoDatePickerDateState extends State { delegate: _DatePickerLayoutDelegate( columnWidths: columnWidths, textDirectionFactor: textDirectionFactor, + maxWidth: maxPickerWidth, ), children: pickers, ), diff --git a/packages/flutter/test/cupertino/date_picker_test.dart b/packages/flutter/test/cupertino/date_picker_test.dart index 918c280c31..812d7818d3 100644 --- a/packages/flutter/test/cupertino/date_picker_test.dart +++ b/packages/flutter/test/cupertino/date_picker_test.dart @@ -592,6 +592,56 @@ void main() { ); }); + testWidgets('width of wheel in background does not increase at large widths', (WidgetTester tester) async { + + final Widget dateWidget = CupertinoDatePicker( + mode: CupertinoDatePickerMode.date, + onDateTimeChanged: (_) { }, + initialDateTime: DateTime(2018, 1, 1, 10, 30), + ); + + await tester.pumpWidget( + CupertinoApp( + home: CupertinoPageScaffold( + child: Center( + child: SizedBox( + height: 200.0, + width: 300.0, + child: dateWidget, + ), + ), + ), + ), + ); + + double decemberX = tester.getBottomLeft(find.text('December')).dx; + double octoberX = tester.getBottomLeft(find.text('October')).dx; + final double distance = octoberX - decemberX; + + await tester.pumpWidget( + CupertinoApp( + home: CupertinoPageScaffold( + child: Center( + child: SizedBox( + height: 200.0, + width: 3000.0, + child: dateWidget, + ), + ), + ), + ), + ); + + decemberX = tester.getBottomLeft(find.text('December')).dx; + octoberX = tester.getBottomLeft(find.text('October')).dx; + + // The wheel does not bend outwards at large widths. + expect( + distance >= (octoberX - decemberX), + true, + ); + }); + testWidgets('picker automatically scrolls away from invalid date on month change', (WidgetTester tester) async { late DateTime date; await tester.pumpWidget(