Updated SearchDelegate to follow custom InputDecorationTheme (#55209)
Updated SearchDelegate to follow InputDecorationTheme
This commit is contained in:
@@ -92,9 +92,10 @@ Future<T?> showSearch<T>({
|
||||
/// ## Handling emojis and other complex characters
|
||||
/// {@macro flutter.widgets.editableText.complexCharacters}
|
||||
abstract class SearchDelegate<T> {
|
||||
|
||||
/// Constructor to be called by subclasses which may specify [searchFieldLabel], [keyboardType] and/or
|
||||
/// [textInputAction].
|
||||
/// Constructor to be called by subclasses which may specify
|
||||
/// [searchFieldLabel], either [searchFieldStyle] or [searchFieldDecorationTheme],
|
||||
/// [keyboardType] and/or [textInputAction]. Only one of [searchFieldLabel]
|
||||
/// and [searchFieldDecorationTheme] may be non-null.
|
||||
///
|
||||
/// {@tool snippet}
|
||||
/// ```dart
|
||||
@@ -124,9 +125,10 @@ abstract class SearchDelegate<T> {
|
||||
SearchDelegate({
|
||||
this.searchFieldLabel,
|
||||
this.searchFieldStyle,
|
||||
this.searchFieldDecorationTheme,
|
||||
this.keyboardType,
|
||||
this.textInputAction = TextInputAction.search,
|
||||
});
|
||||
}) : assert(searchFieldStyle == null || searchFieldDecorationTheme == null);
|
||||
|
||||
/// Suggestions shown in the body of the search page while the user types a
|
||||
/// query into the search field.
|
||||
@@ -205,6 +207,11 @@ abstract class SearchDelegate<T> {
|
||||
primaryIconTheme: theme.primaryIconTheme.copyWith(color: Colors.grey),
|
||||
primaryColorBrightness: Brightness.light,
|
||||
primaryTextTheme: theme.textTheme,
|
||||
inputDecorationTheme: searchFieldDecorationTheme ??
|
||||
InputDecorationTheme(
|
||||
hintStyle: searchFieldStyle ?? theme.inputDecorationTheme.hintStyle,
|
||||
border: InputBorder.none,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -276,8 +283,18 @@ abstract class SearchDelegate<T> {
|
||||
///
|
||||
/// If this value is set to null, the value of the ambient [Theme]'s
|
||||
/// [InputDecorationTheme.hintStyle] will be used instead.
|
||||
///
|
||||
/// If this value is not null, [searchFieldDecorationTheme]
|
||||
/// will be ignored so this can be used.
|
||||
final TextStyle? searchFieldStyle;
|
||||
|
||||
/// The [InputDecorationTheme] for the search field, use
|
||||
/// this if you just want to customize the [TextField]
|
||||
///
|
||||
/// If this value is not null, [searchFieldStyle]
|
||||
/// will be ignored so this can be used.
|
||||
final InputDecorationTheme? searchFieldDecorationTheme;
|
||||
|
||||
/// The type of action button to use for the keyboard.
|
||||
///
|
||||
/// Defaults to the default value specified in [TextField].
|
||||
@@ -482,8 +499,6 @@ class _SearchPageState<T> extends State<_SearchPage<T>> {
|
||||
final ThemeData theme = widget.delegate.appBarTheme(context);
|
||||
final String searchFieldLabel = widget.delegate.searchFieldLabel
|
||||
?? MaterialLocalizations.of(context).searchFieldLabel;
|
||||
final TextStyle? searchFieldStyle = widget.delegate.searchFieldStyle
|
||||
?? theme.inputDecorationTheme.hintStyle;
|
||||
Widget? body;
|
||||
switch(widget.delegate._currentBody) {
|
||||
case _SearchBody.suggestions:
|
||||
@@ -501,7 +516,8 @@ class _SearchPageState<T> extends State<_SearchPage<T>> {
|
||||
case null:
|
||||
break;
|
||||
}
|
||||
final String routeName;
|
||||
|
||||
late final String routeName;
|
||||
switch (theme.platform) {
|
||||
case TargetPlatform.iOS:
|
||||
case TargetPlatform.macOS:
|
||||
@@ -519,33 +535,28 @@ class _SearchPageState<T> extends State<_SearchPage<T>> {
|
||||
scopesRoute: true,
|
||||
namesRoute: true,
|
||||
label: routeName,
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: theme.primaryColor,
|
||||
iconTheme: theme.primaryIconTheme,
|
||||
textTheme: theme.primaryTextTheme,
|
||||
brightness: theme.primaryColorBrightness,
|
||||
leading: widget.delegate.buildLeading(context),
|
||||
title: TextField(
|
||||
controller: widget.delegate._queryTextController,
|
||||
focusNode: focusNode,
|
||||
style: theme.textTheme.headline6,
|
||||
textInputAction: widget.delegate.textInputAction,
|
||||
keyboardType: widget.delegate.keyboardType,
|
||||
onSubmitted: (String _) {
|
||||
widget.delegate.showResults(context);
|
||||
},
|
||||
decoration: InputDecoration(
|
||||
border: InputBorder.none,
|
||||
hintText: searchFieldLabel,
|
||||
hintStyle: searchFieldStyle,
|
||||
child: Theme(
|
||||
data: theme,
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
leading: widget.delegate.buildLeading(context),
|
||||
title: TextField(
|
||||
controller: widget.delegate._queryTextController,
|
||||
focusNode: focusNode,
|
||||
style: theme.textTheme.title,
|
||||
textInputAction: widget.delegate.textInputAction,
|
||||
keyboardType: widget.delegate.keyboardType,
|
||||
onSubmitted: (String _) {
|
||||
widget.delegate.showResults(context);
|
||||
},
|
||||
decoration: InputDecoration(hintText: searchFieldLabel),
|
||||
),
|
||||
actions: widget.delegate.buildActions(context),
|
||||
),
|
||||
body: AnimatedSwitcher(
|
||||
duration: const Duration(milliseconds: 300),
|
||||
child: body,
|
||||
),
|
||||
actions: widget.delegate.buildActions(context),
|
||||
),
|
||||
body: AnimatedSwitcher(
|
||||
duration: const Duration(milliseconds: 300),
|
||||
child: body,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -122,7 +122,8 @@ void main() {
|
||||
});
|
||||
|
||||
testWidgets('Hint text color overridden', (WidgetTester tester) async {
|
||||
final _TestSearchDelegate delegate = _TestSearchDelegate();
|
||||
const String searchHintText = 'Enter search terms';
|
||||
final _TestSearchDelegate delegate = _TestSearchDelegate(searchHint: searchHintText);
|
||||
|
||||
await tester.pumpWidget(TestHomePage(
|
||||
delegate: delegate,
|
||||
@@ -130,9 +131,8 @@ void main() {
|
||||
await tester.tap(find.byTooltip('Search'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final TextField textField = tester.widget<TextField>(find.byType(TextField));
|
||||
final Color hintColor = textField.decoration!.hintStyle!.color!;
|
||||
expect(hintColor, delegate.hintTextColor);
|
||||
final Text hintText = tester.widget(find.text(searchHintText));
|
||||
expect(hintText.style!.color, _TestSearchDelegate.hintTextColor);
|
||||
});
|
||||
|
||||
testWidgets('Requests suggestions', (WidgetTester tester) async {
|
||||
@@ -540,20 +540,18 @@ void main() {
|
||||
});
|
||||
|
||||
testWidgets('Custom searchFieldStyle value', (WidgetTester tester) async {
|
||||
const TextStyle searchStyle = TextStyle(color: Colors.red, fontSize: 3);
|
||||
const String searchHintText = 'Enter search terms';
|
||||
const TextStyle searchFieldStyle = TextStyle(color: Colors.red, fontSize: 3);
|
||||
|
||||
final _TestSearchDelegate delegate = _TestSearchDelegate(searchFieldStyle: searchStyle);
|
||||
final _TestSearchDelegate delegate = _TestSearchDelegate(searchHint: searchHintText, searchFieldStyle: searchFieldStyle);
|
||||
|
||||
await tester.pumpWidget(
|
||||
TestHomePage(
|
||||
delegate: delegate,
|
||||
));
|
||||
await tester.pumpWidget(TestHomePage(delegate: delegate));
|
||||
await tester.tap(find.byTooltip('Search'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final TextField textField = tester.widget<TextField>(find.byType(TextField));
|
||||
final TextStyle hintStyle = textField.decoration!.hintStyle!;
|
||||
expect(hintStyle, delegate.searchFieldStyle);
|
||||
final Text hintText = tester.widget(find.text(searchHintText));
|
||||
expect(hintText.style?.color, delegate.searchFieldStyle?.color);
|
||||
expect(hintText.style?.fontSize, delegate.searchFieldStyle?.fontSize);
|
||||
});
|
||||
|
||||
testWidgets('keyboard show search button by default', (WidgetTester tester) async {
|
||||
@@ -692,6 +690,23 @@ void main() {
|
||||
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
|
||||
});
|
||||
|
||||
testWidgets('Custom searchFieldDecorationTheme value',
|
||||
(WidgetTester tester) async {
|
||||
const InputDecorationTheme searchFieldDecorationTheme = InputDecorationTheme(
|
||||
hintStyle: TextStyle(color: _TestSearchDelegate.hintTextColor),
|
||||
);
|
||||
final _TestSearchDelegate delegate = _TestSearchDelegate(
|
||||
searchFieldDecorationTheme: searchFieldDecorationTheme,
|
||||
);
|
||||
|
||||
await tester.pumpWidget(TestHomePage(delegate: delegate));
|
||||
await tester.tap(find.byTooltip('Search'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final ThemeData? textFieldTheme = Theme.of(tester.element(find.byType(TextField)));
|
||||
expect(textFieldTheme?.inputDecorationTheme, searchFieldDecorationTheme);
|
||||
});
|
||||
|
||||
// Regression test for: https://github.com/flutter/flutter/issues/66781
|
||||
testWidgets('text in search bar contrasts background (light mode)', (WidgetTester tester) async {
|
||||
final ThemeData themeData = ThemeData.light();
|
||||
@@ -709,8 +724,11 @@ void main() {
|
||||
await tester.tap(find.byTooltip('Search'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final AppBar appBar = tester.widget<AppBar>(find.byType(AppBar));
|
||||
expect(appBar.backgroundColor, Colors.white);
|
||||
final Material appBarBackground = tester.widget<Material>(find.descendant(
|
||||
of: find.byType(AppBar),
|
||||
matching: find.byType(Material),
|
||||
));
|
||||
expect(appBarBackground.color, Colors.white);
|
||||
|
||||
final TextField textField = tester.widget<TextField>(find.byType(TextField));
|
||||
expect(textField.style!.color, themeData.textTheme.bodyText1!.color);
|
||||
@@ -734,8 +752,11 @@ void main() {
|
||||
await tester.tap(find.byTooltip('Search'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final AppBar appBar = tester.widget<AppBar>(find.byType(AppBar));
|
||||
expect(appBar.backgroundColor, themeData.primaryColor);
|
||||
final Material appBarBackground = tester.widget<Material>(find.descendant(
|
||||
of: find.byType(AppBar),
|
||||
matching: find.byType(Material),
|
||||
));
|
||||
expect(appBarBackground.color, themeData.primaryColor);
|
||||
|
||||
final TextField textField = tester.widget<TextField>(find.byType(TextField));
|
||||
expect(textField.style!.color, themeData.textTheme.bodyText1!.color);
|
||||
@@ -803,16 +824,22 @@ class _TestSearchDelegate extends SearchDelegate<String> {
|
||||
this.result = 'Result',
|
||||
this.actions = const <Widget>[],
|
||||
this.defaultAppBarTheme = false,
|
||||
InputDecorationTheme? searchFieldDecorationTheme,
|
||||
TextStyle? searchFieldStyle,
|
||||
String? searchHint,
|
||||
TextInputAction textInputAction = TextInputAction.search,
|
||||
}) : super(searchFieldLabel: searchHint, textInputAction: textInputAction, searchFieldStyle: searchFieldStyle);
|
||||
}) : super(
|
||||
searchFieldLabel: searchHint,
|
||||
textInputAction: textInputAction,
|
||||
searchFieldStyle: searchFieldStyle,
|
||||
searchFieldDecorationTheme: searchFieldDecorationTheme,
|
||||
);
|
||||
|
||||
final bool defaultAppBarTheme;
|
||||
final String suggestions;
|
||||
final String result;
|
||||
final List<Widget> actions;
|
||||
final Color hintTextColor = Colors.green;
|
||||
static const Color hintTextColor = Colors.green;
|
||||
|
||||
@override
|
||||
ThemeData appBarTheme(BuildContext context) {
|
||||
@@ -821,7 +848,13 @@ class _TestSearchDelegate extends SearchDelegate<String> {
|
||||
}
|
||||
final ThemeData theme = Theme.of(context)!;
|
||||
return theme.copyWith(
|
||||
inputDecorationTheme: InputDecorationTheme(hintStyle: TextStyle(color: hintTextColor)),
|
||||
inputDecorationTheme: searchFieldDecorationTheme ??
|
||||
InputDecorationTheme(
|
||||
hintStyle: searchFieldStyle ??
|
||||
const TextStyle(
|
||||
color: hintTextColor,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user