Add searchFieldLabel to SearchDelegate in order to show a custom hint (#36409)
* Add searchFieldLabel to SearchDelegate in order to show a custom hint label. * Add support for specifying textInputAction and keyboardType in SearchDelegate
This commit is contained in:
parent
b2497822e8
commit
9f0831624a
@ -89,6 +89,40 @@ Future<T> showSearch<T>({
|
||||
/// for another [showSearch] call.
|
||||
abstract class SearchDelegate<T> {
|
||||
|
||||
/// Constructor to be called by subclasses which may specify [searchFieldLabel], [keyboardType] and/or
|
||||
/// [textInputAction].
|
||||
///
|
||||
/// {@tool sample}
|
||||
/// ```dart
|
||||
/// class CustomSearchHintDelegate extends SearchDelegate {
|
||||
/// CustomSearchHintDelegate({
|
||||
/// String hintText,
|
||||
/// }) : super(
|
||||
/// searchFieldLabel: hintText,
|
||||
/// keyboardType: TextInputType.text,
|
||||
/// textInputAction: TextInputAction.search,
|
||||
/// );
|
||||
///
|
||||
/// @override
|
||||
/// Widget buildLeading(BuildContext context) => Text("leading");
|
||||
///
|
||||
/// @override
|
||||
/// Widget buildSuggestions(BuildContext context) => Text("suggestions");
|
||||
///
|
||||
/// @override
|
||||
/// Widget buildResults(BuildContext context) => Text('results');
|
||||
///
|
||||
/// @override
|
||||
/// List<Widget> buildActions(BuildContext context) => [];
|
||||
/// }
|
||||
/// ```
|
||||
/// {@end-tool}
|
||||
SearchDelegate({
|
||||
this.searchFieldLabel,
|
||||
this.keyboardType,
|
||||
this.textInputAction = TextInputAction.search,
|
||||
});
|
||||
|
||||
/// Suggestions shown in the body of the search page while the user types a
|
||||
/// query into the search field.
|
||||
///
|
||||
@ -225,6 +259,22 @@ abstract class SearchDelegate<T> {
|
||||
..pop(result);
|
||||
}
|
||||
|
||||
/// The hint text that is shown in the search field when it is empty.
|
||||
///
|
||||
/// If this value is set to null, the value of MaterialLocalizations.of(context).searchFieldLabel will be used instead.
|
||||
final String searchFieldLabel;
|
||||
|
||||
/// The type of action button to use for the keyboard.
|
||||
///
|
||||
/// Defaults to the default value specified in [TextField].
|
||||
final TextInputType keyboardType;
|
||||
|
||||
/// The text input action configuring the soft keyboard to a particular action
|
||||
/// button.
|
||||
///
|
||||
/// Defaults to [TextInputAction.search].
|
||||
final TextInputAction textInputAction;
|
||||
|
||||
/// [Animation] triggered when the search pages fades in or out.
|
||||
///
|
||||
/// This animation is commonly used to animate [AnimatedIcon]s of
|
||||
@ -417,7 +467,8 @@ class _SearchPageState<T> extends State<_SearchPage<T>> {
|
||||
Widget build(BuildContext context) {
|
||||
assert(debugCheckHasMaterialLocalizations(context));
|
||||
final ThemeData theme = widget.delegate.appBarTheme(context);
|
||||
final String searchFieldLabel = MaterialLocalizations.of(context).searchFieldLabel;
|
||||
final String searchFieldLabel = widget.delegate.searchFieldLabel
|
||||
?? MaterialLocalizations.of(context).searchFieldLabel;
|
||||
Widget body;
|
||||
switch(widget.delegate._currentBody) {
|
||||
case _SearchBody.suggestions:
|
||||
@ -459,7 +510,8 @@ class _SearchPageState<T> extends State<_SearchPage<T>> {
|
||||
controller: widget.delegate._queryTextController,
|
||||
focusNode: focusNode,
|
||||
style: theme.textTheme.title,
|
||||
textInputAction: TextInputAction.search,
|
||||
textInputAction: widget.delegate.textInputAction,
|
||||
keyboardType: widget.delegate.keyboardType,
|
||||
onSubmitted: (String _) {
|
||||
widget.delegate.showResults(context);
|
||||
},
|
||||
|
@ -479,7 +479,37 @@ void main() {
|
||||
expect(selectedResults, <String>['Result Foo']);
|
||||
});
|
||||
|
||||
testWidgets('keyboard show search button', (WidgetTester tester) async {
|
||||
testWidgets('Custom searchFieldLabel value', (WidgetTester tester) async {
|
||||
const String searchHint = 'custom search hint';
|
||||
final String defaultSearchHint = const DefaultMaterialLocalizations().searchFieldLabel;
|
||||
|
||||
final _TestSearchDelegate delegate = _TestSearchDelegate(searchHint: searchHint);
|
||||
|
||||
await tester.pumpWidget(TestHomePage(
|
||||
delegate: delegate,
|
||||
));
|
||||
await tester.tap(find.byTooltip('Search'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.text(searchHint), findsOneWidget);
|
||||
expect(find.text(defaultSearchHint), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('Default searchFieldLabel is used when it is set to null', (WidgetTester tester) async {
|
||||
final String searchHint = const DefaultMaterialLocalizations().searchFieldLabel;
|
||||
|
||||
final _TestSearchDelegate delegate = _TestSearchDelegate();
|
||||
|
||||
await tester.pumpWidget(TestHomePage(
|
||||
delegate: delegate,
|
||||
));
|
||||
await tester.tap(find.byTooltip('Search'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.text(searchHint), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('keyboard show search button by default', (WidgetTester tester) async {
|
||||
final _TestSearchDelegate delegate = _TestSearchDelegate();
|
||||
|
||||
await tester.pumpWidget(TestHomePage(
|
||||
@ -493,6 +523,18 @@ void main() {
|
||||
expect(tester.testTextInput.setClientArgs['inputAction'], TextInputAction.search.toString());
|
||||
});
|
||||
|
||||
testWidgets('Custom textInputAction results in keyboard with corresponding button', (WidgetTester tester) async {
|
||||
final _TestSearchDelegate delegate = _TestSearchDelegate(textInputAction: TextInputAction.done);
|
||||
|
||||
await tester.pumpWidget(TestHomePage(
|
||||
delegate: delegate,
|
||||
));
|
||||
await tester.tap(find.byTooltip('Search'));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.showKeyboard(find.byType(TextField));
|
||||
expect(tester.testTextInput.setClientArgs['inputAction'], TextInputAction.done.toString());
|
||||
});
|
||||
|
||||
group('contributes semantics', () {
|
||||
TestSemantics buildExpected({ String routeName }) {
|
||||
return TestSemantics.root(
|
||||
@ -649,12 +691,13 @@ class TestHomePage extends StatelessWidget {
|
||||
}
|
||||
|
||||
class _TestSearchDelegate extends SearchDelegate<String> {
|
||||
|
||||
_TestSearchDelegate({
|
||||
this.suggestions = 'Suggestions',
|
||||
this.result = 'Result',
|
||||
this.actions = const <Widget>[],
|
||||
});
|
||||
String searchHint,
|
||||
TextInputAction textInputAction = TextInputAction.search,
|
||||
}) : super(searchFieldLabel: searchHint, textInputAction: textInputAction);
|
||||
|
||||
final String suggestions;
|
||||
final String result;
|
||||
@ -704,4 +747,4 @@ class _TestSearchDelegate extends SearchDelegate<String> {
|
||||
List<Widget> buildActions(BuildContext context) {
|
||||
return actions;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user