fix DropdownMenu crashes when provided menuStyle with small maximumSize (#162380)

<!--
Thanks for filing a pull request!
Reviewers are typically assigned within a week of filing a request.
To learn more about code review, see our documentation on Tree Hygiene:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
-->

fix #162356
Previously `DropdownMenu` overwrites `minimumSize` in `menuStyle` to be
the width of the `TextField`
Now it set the `minimumSize` to be the min between the width of the
`TextField` and the width of `maximumSize`, so that the menu can be
smaller than the `TextField`.

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
This commit is contained in:
PurplePolyhedron 2025-02-13 16:34:37 +10:00 committed by GitHub
parent 1624890a8d
commit 4aafcce483
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 56 additions and 2 deletions

View File

@ -967,11 +967,19 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> {
final double? anchorWidth = getWidth(_anchorKey);
if (widget.width != null) {
effectiveMenuStyle = effectiveMenuStyle.copyWith(
minimumSize: MaterialStatePropertyAll<Size?>(Size(widget.width!, 0.0)),
minimumSize: MaterialStateProperty.resolveWith<Size?>((Set<MaterialState> states) {
final double? effectiveMaximumWidth =
effectiveMenuStyle!.maximumSize?.resolve(states)?.width;
return Size(math.min(widget.width!, effectiveMaximumWidth ?? 0.0), 0.0);
}),
);
} else if (anchorWidth != null) {
effectiveMenuStyle = effectiveMenuStyle.copyWith(
minimumSize: MaterialStatePropertyAll<Size?>(Size(anchorWidth, 0.0)),
minimumSize: MaterialStateProperty.resolveWith<Size?>((Set<MaterialState> states) {
final double? effectiveMaximumWidth =
effectiveMenuStyle!.maximumSize?.resolve(states)?.width;
return Size(math.min(anchorWidth, effectiveMaximumWidth ?? 0.0), 0.0);
}),
);
}

View File

@ -3952,6 +3952,52 @@ void main() {
textField = tester.widget(find.byType(TextField));
expect(textField.textInputAction, TextInputAction.next);
});
testWidgets('items can be constrainted to be smaller than the text field with menuStyle', (
WidgetTester tester,
) async {
const String longLabel = 'This is a long text that it can overflow.';
await tester.pumpWidget(
const MaterialApp(
home: Scaffold(
body: DropdownMenu<int>(
dropdownMenuEntries: <DropdownMenuEntry<int>>[
DropdownMenuEntry<int>(value: 0, label: longLabel),
],
menuStyle: MenuStyle(maximumSize: WidgetStatePropertyAll<Size>(Size(150.0, 50.0))),
),
),
),
);
await tester.tap(find.byType(TextField));
await tester.pumpAndSettle();
expect(tester.takeException(), isNull);
expect(tester.getSize(findMenuItemButton(longLabel)).width, 150.0);
// The overwrite of menuStyle is different when a width is provided,
// So it needs to be tested separately.
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: DropdownMenu<TestMenu>(
width: 200.0,
dropdownMenuEntries: menuChildren,
menuStyle: const MenuStyle(
maximumSize: WidgetStatePropertyAll<Size>(Size(150.0, 50.0)),
),
),
),
),
);
await tester.tap(find.byType(TextField));
await tester.pumpAndSettle();
expect(tester.takeException(), isNull);
expect(tester.getSize(findMenuItemButton(menuChildren.first.label)).width, 150.0);
});
}
enum TestMenu {