Delay DropdownMenu
filtering until text input (#152368)
fixes https://github.com/flutter/flutter/issues/152055 Disabling filtering in `DropdownMenu` at start and after a selection has been made, and re-enable it (if `widget.enableFilter` is true) after text input. This way it doesn't hide all other options when there is an existing selection. Note: currently this may crush due to issue https://github.com/flutter/flutter/issues/151878 . Which is not directly related to this PR
This commit is contained in:
parent
6ef1156f7e
commit
b5847d364a
@ -488,7 +488,7 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> {
|
||||
final GlobalKey _leadingKey = GlobalKey();
|
||||
late List<GlobalKey> buttonItemKeys;
|
||||
final MenuController _controller = MenuController();
|
||||
late bool _enableFilter;
|
||||
bool _enableFilter = false;
|
||||
late List<DropdownMenuEntry<T>> filteredEntries;
|
||||
List<Widget>? _initialMenu;
|
||||
int? currentHighlight;
|
||||
@ -504,7 +504,6 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> {
|
||||
} else {
|
||||
_localTextEditingController = TextEditingController();
|
||||
}
|
||||
_enableFilter = widget.enableFilter;
|
||||
filteredEntries = widget.dropdownMenuEntries;
|
||||
buttonItemKeys = List<GlobalKey>.generate(filteredEntries.length, (int index) => GlobalKey());
|
||||
_menuHasEnabledItem = filteredEntries.any((DropdownMenuEntry<T> entry) => entry.enabled);
|
||||
@ -537,6 +536,11 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> {
|
||||
}
|
||||
_localTextEditingController = widget.controller ?? TextEditingController();
|
||||
}
|
||||
if (oldWidget.enableFilter != widget.enableFilter) {
|
||||
if (!widget.enableFilter) {
|
||||
_enableFilter = false;
|
||||
}
|
||||
}
|
||||
if (oldWidget.enableSearch != widget.enableSearch) {
|
||||
if (!widget.enableSearch) {
|
||||
currentHighlight = null;
|
||||
@ -676,6 +680,7 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> {
|
||||
);
|
||||
currentHighlight = widget.enableSearch ? i : null;
|
||||
widget.onSelected?.call(entry.value);
|
||||
_enableFilter = false;
|
||||
}
|
||||
: null,
|
||||
requestFocusOnHover: false,
|
||||
@ -748,6 +753,8 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> {
|
||||
if (_enableFilter) {
|
||||
filteredEntries = widget.filterCallback?.call(filteredEntries, _localTextEditingController!.text)
|
||||
?? filter(widget.dropdownMenuEntries, _localTextEditingController!);
|
||||
} else {
|
||||
filteredEntries = widget.dropdownMenuEntries;
|
||||
}
|
||||
|
||||
if (widget.enableSearch) {
|
||||
|
@ -2524,6 +2524,49 @@ void main() {
|
||||
|
||||
expect(menuAnchor.alignmentOffset, alignmentOffset);
|
||||
});
|
||||
|
||||
testWidgets('DropdownMenu filter is disabled until text input', (WidgetTester tester) async{
|
||||
await tester.pumpWidget(MaterialApp(
|
||||
home: Scaffold(
|
||||
body: DropdownMenu<TestMenu>(
|
||||
requestFocusOnTap: true,
|
||||
enableFilter: true,
|
||||
initialSelection: menuChildren[0].value,
|
||||
dropdownMenuEntries: menuChildren,
|
||||
),
|
||||
),
|
||||
));
|
||||
|
||||
await tester.tap(find.byType(DropdownMenu<TestMenu>));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// All entries should be available, and two buttons should be found for each entry.
|
||||
// One is layout for the _DropdownMenuBody, the other one is the real button item in the menu.
|
||||
for (final TestMenu menu in TestMenu.values) {
|
||||
expect(find.widgetWithText(MenuItemButton, menu.label), findsNWidgets(2));
|
||||
}
|
||||
|
||||
// Text input would enable the filter.
|
||||
await tester.enterText(find.byType(TextField).first, 'Menu 1');
|
||||
await tester.pumpAndSettle();
|
||||
for (final TestMenu menu in TestMenu.values) {
|
||||
// 'Menu 1' should be 2, other items should only find one.
|
||||
if (menu.label == TestMenu.mainMenu1.label) {
|
||||
expect(find.widgetWithText(MenuItemButton, menu.label), findsNWidgets(2));
|
||||
} else {
|
||||
expect(find.widgetWithText(MenuItemButton, menu.label), findsOneWidget);
|
||||
}
|
||||
}
|
||||
|
||||
// Selecting an item would disable filter again.
|
||||
await tester.tap(find.widgetWithText(MenuItemButton, 'Menu 1').last);
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.byType(DropdownMenu<TestMenu>));
|
||||
await tester.pumpAndSettle();
|
||||
for (final TestMenu menu in TestMenu.values) {
|
||||
expect(find.widgetWithText(MenuItemButton, menu.label), findsNWidgets(2));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
enum TestMenu {
|
||||
|
Loading…
x
Reference in New Issue
Block a user