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.
|
/// for another [showSearch] call.
|
||||||
abstract class SearchDelegate<T> {
|
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
|
/// Suggestions shown in the body of the search page while the user types a
|
||||||
/// query into the search field.
|
/// query into the search field.
|
||||||
///
|
///
|
||||||
@ -225,6 +259,22 @@ abstract class SearchDelegate<T> {
|
|||||||
..pop(result);
|
..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.
|
/// [Animation] triggered when the search pages fades in or out.
|
||||||
///
|
///
|
||||||
/// This animation is commonly used to animate [AnimatedIcon]s of
|
/// 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) {
|
Widget build(BuildContext context) {
|
||||||
assert(debugCheckHasMaterialLocalizations(context));
|
assert(debugCheckHasMaterialLocalizations(context));
|
||||||
final ThemeData theme = widget.delegate.appBarTheme(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;
|
Widget body;
|
||||||
switch(widget.delegate._currentBody) {
|
switch(widget.delegate._currentBody) {
|
||||||
case _SearchBody.suggestions:
|
case _SearchBody.suggestions:
|
||||||
@ -459,7 +510,8 @@ class _SearchPageState<T> extends State<_SearchPage<T>> {
|
|||||||
controller: widget.delegate._queryTextController,
|
controller: widget.delegate._queryTextController,
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
style: theme.textTheme.title,
|
style: theme.textTheme.title,
|
||||||
textInputAction: TextInputAction.search,
|
textInputAction: widget.delegate.textInputAction,
|
||||||
|
keyboardType: widget.delegate.keyboardType,
|
||||||
onSubmitted: (String _) {
|
onSubmitted: (String _) {
|
||||||
widget.delegate.showResults(context);
|
widget.delegate.showResults(context);
|
||||||
},
|
},
|
||||||
|
@ -479,7 +479,37 @@ void main() {
|
|||||||
expect(selectedResults, <String>['Result Foo']);
|
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();
|
final _TestSearchDelegate delegate = _TestSearchDelegate();
|
||||||
|
|
||||||
await tester.pumpWidget(TestHomePage(
|
await tester.pumpWidget(TestHomePage(
|
||||||
@ -493,6 +523,18 @@ void main() {
|
|||||||
expect(tester.testTextInput.setClientArgs['inputAction'], TextInputAction.search.toString());
|
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', () {
|
group('contributes semantics', () {
|
||||||
TestSemantics buildExpected({ String routeName }) {
|
TestSemantics buildExpected({ String routeName }) {
|
||||||
return TestSemantics.root(
|
return TestSemantics.root(
|
||||||
@ -649,12 +691,13 @@ class TestHomePage extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _TestSearchDelegate extends SearchDelegate<String> {
|
class _TestSearchDelegate extends SearchDelegate<String> {
|
||||||
|
|
||||||
_TestSearchDelegate({
|
_TestSearchDelegate({
|
||||||
this.suggestions = 'Suggestions',
|
this.suggestions = 'Suggestions',
|
||||||
this.result = 'Result',
|
this.result = 'Result',
|
||||||
this.actions = const <Widget>[],
|
this.actions = const <Widget>[],
|
||||||
});
|
String searchHint,
|
||||||
|
TextInputAction textInputAction = TextInputAction.search,
|
||||||
|
}) : super(searchFieldLabel: searchHint, textInputAction: textInputAction);
|
||||||
|
|
||||||
final String suggestions;
|
final String suggestions;
|
||||||
final String result;
|
final String result;
|
||||||
@ -704,4 +747,4 @@ class _TestSearchDelegate extends SearchDelegate<String> {
|
|||||||
List<Widget> buildActions(BuildContext context) {
|
List<Widget> buildActions(BuildContext context) {
|
||||||
return actions;
|
return actions;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user