SearchBar should listen to changes to the SearchController and update suggestions on change (#134337)
This PR is adding a listener to the `SearchController`, so that the `suggestionBuilder` can be updated when the `SearchController` changes. Another method we can possibly do is have an update method on `SearchController`, so that the user can manually update the suggestions instead of us doing it automatically. Fixes #132161
This commit is contained in:
parent
3e60999b11
commit
d9c0d3ae51
@ -673,11 +673,19 @@ class _ViewContentState extends State<_ViewContent> {
|
||||
super.initState();
|
||||
_viewRect = widget.viewRect;
|
||||
_controller = widget.searchController;
|
||||
_controller.addListener(updateSuggestions);
|
||||
|
||||
if (!_focusNode.hasFocus) {
|
||||
_focusNode.requestFocus();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose(){
|
||||
_controller.removeListener(updateSuggestions);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(covariant _ViewContent oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
@ -737,7 +745,6 @@ class _ViewContentState extends State<_ViewContent> {
|
||||
icon: const Icon(Icons.close),
|
||||
onPressed: () {
|
||||
_controller.clear();
|
||||
updateSuggestions();
|
||||
},
|
||||
),
|
||||
];
|
||||
|
@ -1490,6 +1490,95 @@ void main() {
|
||||
expect(controller.value.text, suggestion);
|
||||
});
|
||||
|
||||
testWidgets('SearchAnchor should update suggestions on changes to search controller', (WidgetTester tester) async {
|
||||
final SearchController controller = SearchController();
|
||||
const List<String> suggestions = <String>['foo','far','bim'];
|
||||
addTearDown(controller.dispose);
|
||||
|
||||
await tester.pumpWidget(MaterialApp(
|
||||
home: StatefulBuilder(
|
||||
builder: (BuildContext context, StateSetter setState) {
|
||||
return Material(
|
||||
child: Align(
|
||||
alignment: Alignment.topCenter,
|
||||
child: SearchAnchor(
|
||||
searchController: controller,
|
||||
builder: (BuildContext context, SearchController controller) {
|
||||
return const Icon(Icons.search);
|
||||
},
|
||||
suggestionsBuilder: (BuildContext context, SearchController controller) {
|
||||
final String searchText = controller.text.toLowerCase();
|
||||
if (searchText.isEmpty) {
|
||||
return const <Widget>[
|
||||
Center(
|
||||
child: Text('No Search'),
|
||||
),
|
||||
];
|
||||
}
|
||||
final Iterable<String> filterSuggestions = suggestions.where(
|
||||
(String suggestion) => suggestion.toLowerCase().contains(searchText),
|
||||
);
|
||||
return filterSuggestions.map((String suggestion) {
|
||||
return ListTile(
|
||||
title: Text(suggestion),
|
||||
trailing: IconButton(
|
||||
icon: const Icon(Icons.call_missed),
|
||||
onPressed: () {
|
||||
controller.text = suggestion;
|
||||
},
|
||||
),
|
||||
onTap: () {
|
||||
controller.closeView(suggestion);
|
||||
},
|
||||
);
|
||||
}).toList();
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
),
|
||||
));
|
||||
|
||||
await tester.tap(find.byIcon(Icons.search));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final Finder listTile1 = find.widgetWithText(ListTile, 'foo');
|
||||
final Finder listTile2 = find.widgetWithText(ListTile, 'far');
|
||||
final Finder listTile3 = find.widgetWithText(ListTile, 'bim');
|
||||
final Finder textWidget = find.widgetWithText(Center, 'No Search');
|
||||
final Finder iconInListTile1 = find.descendant(of: listTile1, matching: find.byIcon(Icons.call_missed));
|
||||
|
||||
expect(textWidget,findsOneWidget);
|
||||
expect(listTile1, findsNothing);
|
||||
expect(listTile2, findsNothing);
|
||||
expect(listTile3, findsNothing);
|
||||
|
||||
await tester.enterText(find.byType(SearchBar), 'f');
|
||||
await tester.pumpAndSettle();
|
||||
expect(textWidget,findsNothing);
|
||||
expect(listTile1, findsOneWidget);
|
||||
expect(listTile2, findsOneWidget);
|
||||
expect(listTile3, findsNothing);
|
||||
|
||||
await tester.tap(iconInListTile1);
|
||||
await tester.pumpAndSettle();
|
||||
expect(controller.value.text, 'foo');
|
||||
expect(textWidget,findsNothing);
|
||||
expect(listTile1, findsOneWidget);
|
||||
expect(listTile2, findsNothing);
|
||||
expect(listTile3, findsNothing);
|
||||
|
||||
await tester.tap(listTile1);
|
||||
await tester.pumpAndSettle();
|
||||
expect(controller.isOpen, false);
|
||||
expect(controller.value.text, 'foo');
|
||||
expect(textWidget,findsNothing);
|
||||
expect(listTile1, findsNothing);
|
||||
expect(listTile2, findsNothing);
|
||||
expect(listTile3, findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('SearchAnchor suggestionsBuilder property could be async', (WidgetTester tester) async {
|
||||
final SearchController controller = SearchController();
|
||||
const String suggestion = 'suggestion text';
|
||||
|
Loading…
x
Reference in New Issue
Block a user