Unverified Commit a0943e65 authored by Taha Tesser's avatar Taha Tesser Committed by GitHub

Fix `DatePickerDialog` & `DateRangePickerDialog` overflow when resized from...

Fix  `DatePickerDialog` & `DateRangePickerDialog` overflow when resized from landscape to portrait (#133327)

fixes [resize window with a `showDateRangePicker` will make RenderFlex overflowed error](https://github.com/flutter/flutter/issues/131989)

### Description
- This fixes  `DatePickerDialog` & `DateRangePickerDialog` overflow error when resized from landscape to portrait.
- Added tests that check these two widgets from landscape to portrait for no overflow errors.

<details
<summary>expand to view the code sample</summary> 

```dart
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Example(),
    );
  }
}

class Example extends StatefulWidget {
  const Example({super.key});

  @override
  State<Example> createState() => _ExampleState();
}

class _ExampleState extends State<Example> {
  bool _portait = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('DatePicker & DateRangePicker'),
      ),
      body: MediaQuery(
        data: MediaQuery.of(context).copyWith(
          size: _portait ? const Size(400, 800) : const Size(800, 400),
        ),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            DatePickerDialog(
              initialDate: DateTime.now(),
              firstDate: DateTime(2020),
              lastDate: DateTime(2030),
              initialEntryMode: DatePickerEntryMode.inputOnly,
            ),
            DateRangePickerDialog(
              currentDate: DateTime.now(),
              firstDate: DateTime(2020),
              lastDate: DateTime(2030),
              initialEntryMode: DatePickerEntryMode.inputOnly,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          setState(() {
            _portait = !_portait;
          });
        },
        child: const Icon(Icons.refresh),
      ),
    );
  }
}

```

</details>

### Before

https://github.com/flutter/flutter/assets/48603081/81387cbb-cdcf-42bd-b4f8-b7a08317c955

### After

https://github.com/flutter/flutter/assets/48603081/36d28ea9-cfed-48ad-90f5-0459755e08c0
parent e7fc5a6e
...@@ -674,7 +674,12 @@ class _DatePickerDialogState extends State<DatePickerDialog> with RestorationMix ...@@ -674,7 +674,12 @@ class _DatePickerDialogState extends State<DatePickerDialog> with RestorationMix
// Constrain the textScaleFactor to the largest supported value to prevent // Constrain the textScaleFactor to the largest supported value to prevent
// layout issues. // layout issues.
maxScaleFactor: _kMaxTextScaleFactor, maxScaleFactor: _kMaxTextScaleFactor,
child: Builder(builder: (BuildContext context) { child: LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) {
final Size portraitDialogSize = useMaterial3 ? _inputPortraitDialogSizeM3 : _inputPortraitDialogSizeM2;
// Make sure the portrait dialog can fit the contents comfortably when
// resized from the landscape dialog.
final bool isFullyPortrait = constraints.maxHeight >= portraitDialogSize.height;
switch (orientation) { switch (orientation) {
case Orientation.portrait: case Orientation.portrait:
return Column( return Column(
...@@ -683,8 +688,10 @@ class _DatePickerDialogState extends State<DatePickerDialog> with RestorationMix ...@@ -683,8 +688,10 @@ class _DatePickerDialogState extends State<DatePickerDialog> with RestorationMix
children: <Widget>[ children: <Widget>[
header, header,
if (useMaterial3) Divider(height: 0, color: datePickerTheme.dividerColor), if (useMaterial3) Divider(height: 0, color: datePickerTheme.dividerColor),
Expanded(child: picker), if (isFullyPortrait) ...<Widget>[
actions, Expanded(child: picker),
actions,
],
], ],
); );
case Orientation.landscape: case Orientation.landscape:
...@@ -2775,14 +2782,25 @@ class _InputDateRangePickerDialog extends StatelessWidget { ...@@ -2775,14 +2782,25 @@ class _InputDateRangePickerDialog extends StatelessWidget {
switch (orientation) { switch (orientation) {
case Orientation.portrait: case Orientation.portrait:
return Column( return LayoutBuilder(
mainAxisSize: MainAxisSize.min, builder: (BuildContext context, BoxConstraints constraints) {
crossAxisAlignment: CrossAxisAlignment.stretch, final Size portraitDialogSize = useMaterial3 ? _inputPortraitDialogSizeM3 : _inputPortraitDialogSizeM2;
children: <Widget>[ // Make sure the portrait dialog can fit the contents comfortably when
header, // resized from the landscape dialog.
Expanded(child: picker), final bool isFullyPortrait = constraints.maxHeight >= portraitDialogSize.height;
actions,
], return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
header,
if (isFullyPortrait) ...<Widget>[
Expanded(child: picker),
actions,
],
],
);
}
); );
case Orientation.landscape: case Orientation.landscape:
......
...@@ -1469,6 +1469,22 @@ void main() { ...@@ -1469,6 +1469,22 @@ void main() {
expect(tester.takeException(), null); expect(tester.takeException(), null);
}); });
}); });
// This is a regression test for https://github.com/flutter/flutter/issues/131989.
testWidgets('Dialog contents do not overflow when resized from landscape to portrait',
(WidgetTester tester) async {
addTearDown(tester.view.reset);
// Initial window size is wide for landscape mode.
tester.view.physicalSize = wideWindowSize;
tester.view.devicePixelRatio = 1.0;
await prepareDatePicker(tester, (Future<DateTime?> date) async {
// Change window size to narrow for portrait mode.
tester.view.physicalSize = narrowWindowSize;
await tester.pump();
expect(tester.takeException(), null);
});
});
}); });
group('Semantics', () { group('Semantics', () {
......
...@@ -53,6 +53,9 @@ void main() { ...@@ -53,6 +53,9 @@ void main() {
saveText = null; saveText = null;
}); });
const Size wideWindowSize = Size(1920.0, 1080.0);
const Size narrowWindowSize = Size(1070.0, 1770.0);
Future<void> preparePicker( Future<void> preparePicker(
WidgetTester tester, WidgetTester tester,
Future<void> Function(Future<DateTimeRange?> date) callback, { Future<void> Function(Future<DateTimeRange?> date) callback, {
...@@ -1065,6 +1068,22 @@ void main() { ...@@ -1065,6 +1068,22 @@ void main() {
// Test the end date text field // Test the end date text field
testInputDecorator(tester.widget(borderContainers.last), border, Colors.transparent); testInputDecorator(tester.widget(borderContainers.last), border, Colors.transparent);
}); });
// This is a regression test for https://github.com/flutter/flutter/issues/131989.
testWidgets('Dialog contents do not overflow when resized from landscape to portrait',
(WidgetTester tester) async {
addTearDown(tester.view.reset);
// Initial window size is wide for landscape mode.
tester.view.physicalSize = wideWindowSize;
tester.view.devicePixelRatio = 1.0;
await preparePicker(tester, (Future<DateTimeRange?> range) async {
// Change window size to narrow for portrait mode.
tester.view.physicalSize = narrowWindowSize;
await tester.pump();
expect(tester.takeException(), null);
});
});
}); });
testWidgets('DatePickerDialog is state restorable', (WidgetTester tester) async { testWidgets('DatePickerDialog is state restorable', (WidgetTester tester) async {
......
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