Unverified Commit 48a9fc13 authored by Gildásio Filho's avatar Gildásio Filho Committed by GitHub

Updated SearchDelegate to follow custom InputDecorationTheme (#55209)

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