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
// Constrain the textScaleFactor to the largest supported value to prevent
// layout issues.
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) {
case Orientation.portrait:
return Column(
......@@ -683,8 +688,10 @@ class _DatePickerDialogState extends State<DatePickerDialog> with RestorationMix
children: <Widget>[
header,
if (useMaterial3) Divider(height: 0, color: datePickerTheme.dividerColor),
Expanded(child: picker),
actions,
if (isFullyPortrait) ...<Widget>[
Expanded(child: picker),
actions,
],
],
);
case Orientation.landscape:
......@@ -2775,14 +2782,25 @@ class _InputDateRangePickerDialog extends StatelessWidget {
switch (orientation) {
case Orientation.portrait:
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
header,
Expanded(child: picker),
actions,
],
return 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;
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
header,
if (isFullyPortrait) ...<Widget>[
Expanded(child: picker),
actions,
],
],
);
}
);
case Orientation.landscape:
......
......@@ -1469,6 +1469,22 @@ void main() {
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', () {
......
......@@ -53,6 +53,9 @@ void main() {
saveText = null;
});
const Size wideWindowSize = Size(1920.0, 1080.0);
const Size narrowWindowSize = Size(1070.0, 1770.0);
Future<void> preparePicker(
WidgetTester tester,
Future<void> Function(Future<DateTimeRange?> date) callback, {
......@@ -1065,6 +1068,22 @@ void main() {
// Test the end date text field
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 {
......
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