Fix DropdownMenu menu is detached from the text field (#159665)
## Description This PR fixes `DropdownMenu` menu vertical position when tight constraints are given to the `DropdownMenu`. Before:  After:  ## Related Issue Fixes [DropdownMenu does not correctly handle incoming maxWidth and minHeight constraints](https://github.com/flutter/flutter/issues/147076). (It fixes the minHeight part, the maxWidth part was already fixed in https://github.com/flutter/flutter/pull/147233). ## Tests Adds 4 tests.
This commit is contained in:
parent
f66f6a7cb9
commit
11fa41e699
@ -1022,6 +1022,17 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Wrap the menu anchor with an Align to narrow down the constraints.
|
||||||
|
// Without this Align, when tight constraints are applied to DropdownMenu,
|
||||||
|
// the menu will appear below these constraints instead of below the
|
||||||
|
// text field.
|
||||||
|
menuAnchor = Align(
|
||||||
|
alignment: AlignmentDirectional.topStart,
|
||||||
|
widthFactor: 1.0,
|
||||||
|
heightFactor: 1.0,
|
||||||
|
child: menuAnchor,
|
||||||
|
);
|
||||||
|
|
||||||
return Actions(
|
return Actions(
|
||||||
actions: <Type, Action<Intent>>{
|
actions: <Type, Action<Intent>>{
|
||||||
_ArrowUpIntent: CallbackAction<_ArrowUpIntent>(
|
_ArrowUpIntent: CallbackAction<_ArrowUpIntent>(
|
||||||
|
@ -3488,6 +3488,94 @@ void main() {
|
|||||||
// None of the menus should be closed.
|
// None of the menus should be closed.
|
||||||
expect(dropdownMenuAnchor.controller!.isOpen, true);
|
expect(dropdownMenuAnchor.controller!.isOpen, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
group('The menu is attached at the bottom of the TextField', () {
|
||||||
|
// Define the expected text field bottom instead of querying it using
|
||||||
|
// tester.getRect because when tight constraints are applied to the
|
||||||
|
// Dropdown the TextField bounds are expanded while the visible size
|
||||||
|
// remains 56 pixels.
|
||||||
|
const double textFieldBottom = 56.0;
|
||||||
|
|
||||||
|
testWidgets('when given loose constraints and expandedInsets is set', (WidgetTester tester) async {
|
||||||
|
await tester.pumpWidget(MaterialApp(
|
||||||
|
home: Scaffold(
|
||||||
|
body: DropdownMenu<TestMenu>(
|
||||||
|
expandedInsets: EdgeInsets.zero,
|
||||||
|
initialSelection: TestMenu.mainMenu3,
|
||||||
|
dropdownMenuEntries: menuChildrenWithIcons,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
// Open the menu.
|
||||||
|
await tester.tap(find.byType(TextField));
|
||||||
|
await tester.pump();
|
||||||
|
|
||||||
|
expect(tester.getRect(findMenuMaterial()).top, textFieldBottom);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('when given tight constraints and expandedInsets is set', (WidgetTester tester) async {
|
||||||
|
await tester.pumpWidget(MaterialApp(
|
||||||
|
home: Scaffold(
|
||||||
|
body: SizedBox(
|
||||||
|
width: 200,
|
||||||
|
height: 300,
|
||||||
|
child: DropdownMenu<TestMenu>(
|
||||||
|
expandedInsets: EdgeInsets.zero,
|
||||||
|
initialSelection: TestMenu.mainMenu3,
|
||||||
|
dropdownMenuEntries: menuChildrenWithIcons,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
// Open the menu.
|
||||||
|
await tester.tap(find.byType(TextField));
|
||||||
|
await tester.pump();
|
||||||
|
|
||||||
|
expect(tester.getRect(findMenuMaterial()).top, textFieldBottom);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Regression test for https://github.com/flutter/flutter/issues/147076.
|
||||||
|
testWidgets('when given loose constraints and expandedInsets is not set', (WidgetTester tester) async {
|
||||||
|
await tester.pumpWidget(MaterialApp(
|
||||||
|
home: Scaffold(
|
||||||
|
body: DropdownMenu<TestMenu>(
|
||||||
|
initialSelection: TestMenu.mainMenu3,
|
||||||
|
dropdownMenuEntries: menuChildrenWithIcons,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
// Open the menu.
|
||||||
|
await tester.tap(find.byType(TextField));
|
||||||
|
await tester.pump();
|
||||||
|
|
||||||
|
expect(tester.getRect(findMenuMaterial()).top, textFieldBottom);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Regression test for https://github.com/flutter/flutter/issues/147076.
|
||||||
|
testWidgets('when given tight constraints and expandedInsets is not set', (WidgetTester tester) async {
|
||||||
|
await tester.pumpWidget(MaterialApp(
|
||||||
|
home: Scaffold(
|
||||||
|
body: SizedBox(
|
||||||
|
width: 200,
|
||||||
|
height: 300,
|
||||||
|
child: DropdownMenu<TestMenu>(
|
||||||
|
initialSelection: TestMenu.mainMenu3,
|
||||||
|
dropdownMenuEntries: menuChildrenWithIcons,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
// Open the menu.
|
||||||
|
await tester.tap(find.byType(TextField));
|
||||||
|
await tester.pump();
|
||||||
|
|
||||||
|
expect(tester.getRect(findMenuMaterial()).top, textFieldBottom);
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
enum TestMenu {
|
enum TestMenu {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user