mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Fix DropdownMenu keyboard navigation (#147294)
Fix https://github.com/flutter/flutter/issues/147253 Fix https://github.com/flutter/flutter/issues/147516 Resubmitted https://github.com/flutter/flutter/pull/147285 because I accidentally added reviewer as contributor in a commit by using Github "add suggestion to batch". Which causing CLA check to fail and I cannot revert it. I use exact match of label instead of contains to minimise possible change in actual user search. I added the new test after the original keyboard navigation test to avoid merge conflict with another incoming PR. Let me know if I need to make any changes. Sorry for the inconvenience, I am new to the process.
This commit is contained in:
parent
da9712f76f
commit
fdfc408fd7
@ -550,6 +550,9 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> {
|
||||
if (searchText.isEmpty) {
|
||||
return null;
|
||||
}
|
||||
if (currentHighlight != null && entries[currentHighlight!].label.toLowerCase().contains(searchText)) {
|
||||
return currentHighlight;
|
||||
}
|
||||
final int index = entries.indexWhere((DropdownMenuEntry<T> entry) => entry.label.toLowerCase().contains(searchText));
|
||||
|
||||
return index != -1 ? index : null;
|
||||
|
||||
@ -764,6 +764,116 @@ void main() {
|
||||
expect(item5material.color, Colors.transparent); // the previous item should not be highlighted.
|
||||
}, variant: TargetPlatformVariant.desktop());
|
||||
|
||||
// Regression test for https://github.com/flutter/flutter/issues/147253.
|
||||
testWidgets('Down key and up key can navigate on desktop platforms '
|
||||
'when a label text contains another label text', (WidgetTester tester) async {
|
||||
final ThemeData themeData = ThemeData();
|
||||
await tester.pumpWidget(MaterialApp(
|
||||
theme: themeData,
|
||||
home: const Scaffold(
|
||||
body: DropdownMenu<int>(
|
||||
dropdownMenuEntries: <DropdownMenuEntry<int>>[
|
||||
DropdownMenuEntry<int>(
|
||||
value: 0,
|
||||
label: 'ABC'
|
||||
),
|
||||
DropdownMenuEntry<int>(
|
||||
value: 1,
|
||||
label: 'AB'
|
||||
),
|
||||
DropdownMenuEntry<int>(
|
||||
value: 2,
|
||||
label: 'ABCD'
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
));
|
||||
|
||||
await tester.tap(find.byType(DropdownMenu<int>));
|
||||
await tester.pump();
|
||||
|
||||
final Finder button0Material = find.descendant(
|
||||
of: find.widgetWithText(MenuItemButton, 'ABC').last,
|
||||
matching: find.byType(Material),
|
||||
);
|
||||
final Finder button1Material = find.descendant(
|
||||
of: find.widgetWithText(MenuItemButton, 'AB').last,
|
||||
matching: find.byType(Material),
|
||||
);
|
||||
final Finder button2Material = find.descendant(
|
||||
of: find.widgetWithText(MenuItemButton, 'ABCD').last,
|
||||
matching: find.byType(Material),
|
||||
);
|
||||
|
||||
// Press down key three times, the highlight should move to the next item each time.
|
||||
await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
|
||||
await tester.pumpAndSettle();
|
||||
Material item0Material = tester.widget<Material>(button0Material);
|
||||
expect(item0Material.color, themeData.colorScheme.onSurface.withOpacity(0.12));
|
||||
|
||||
await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
|
||||
await tester.pumpAndSettle();
|
||||
Material item1Material = tester.widget<Material>(button1Material);
|
||||
expect(item1Material.color, themeData.colorScheme.onSurface.withOpacity(0.12));
|
||||
|
||||
await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
|
||||
await tester.pumpAndSettle();
|
||||
final Material item2Material = tester.widget<Material>(button2Material);
|
||||
expect(item2Material.color, themeData.colorScheme.onSurface.withOpacity(0.12));
|
||||
|
||||
// Press up key two times, the highlight should up each time.
|
||||
await tester.sendKeyEvent(LogicalKeyboardKey.arrowUp);
|
||||
await tester.pumpAndSettle();
|
||||
item1Material = tester.widget<Material>(button1Material);
|
||||
expect(item1Material.color, themeData.colorScheme.onSurface.withOpacity(0.12));
|
||||
|
||||
await tester.sendKeyEvent(LogicalKeyboardKey.arrowUp);
|
||||
await tester.pumpAndSettle();
|
||||
item0Material = tester.widget<Material>(button0Material);
|
||||
expect(item0Material.color, themeData.colorScheme.onSurface.withOpacity(0.12));
|
||||
|
||||
}, variant: TargetPlatformVariant.desktop());
|
||||
|
||||
// Regression test for https://github.com/flutter/flutter/issues/147253.
|
||||
testWidgets('Default search prioritises the current highlight on desktop platforms',
|
||||
(WidgetTester tester) async {
|
||||
final ThemeData themeData = ThemeData();
|
||||
await tester.pumpWidget(MaterialApp(
|
||||
theme: themeData,
|
||||
home: Scaffold(
|
||||
body: DropdownMenu<TestMenu>(
|
||||
dropdownMenuEntries: menuChildren,
|
||||
),
|
||||
),
|
||||
));
|
||||
|
||||
const String itemLabel = 'Item 2';
|
||||
// Open the menu
|
||||
await tester.tap(find.byType(DropdownMenu<TestMenu>));
|
||||
await tester.pumpAndSettle();
|
||||
// Highlight the third item by exact search.
|
||||
await tester.enterText(find.byType(TextField).first, itemLabel);
|
||||
await tester.pumpAndSettle();
|
||||
Finder button2Material = find.descendant(
|
||||
of: find.widgetWithText(MenuItemButton, itemLabel).last,
|
||||
matching: find.byType(Material),
|
||||
);
|
||||
Material item2material = tester.widget<Material>(button2Material);
|
||||
expect(item2material.color, themeData.colorScheme.onSurface.withOpacity(0.12));
|
||||
|
||||
// Search something that matches multiple items.
|
||||
await tester.enterText(find.byType(TextField).first, 'Item');
|
||||
await tester.pumpAndSettle();
|
||||
// The third item should still be highlighted.
|
||||
button2Material = find.descendant(
|
||||
of: find.widgetWithText(MenuItemButton, itemLabel).last,
|
||||
matching: find.byType(Material),
|
||||
);
|
||||
item2material = tester.widget<Material>(button2Material);
|
||||
expect(item2material.color, themeData.colorScheme.onSurface.withOpacity(0.12));
|
||||
}, variant: TargetPlatformVariant.desktop());
|
||||
|
||||
testWidgets('The text input should match the label of the menu item '
|
||||
'while pressing down key on desktop platforms', (WidgetTester tester) async {
|
||||
final ThemeData themeData = ThemeData();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user