Unverified Commit ef794e2a authored by Qun Cheng's avatar Qun Cheng Committed by GitHub

Add `headerHeight` for `SearchAnchor` (#141223)

Fixes #140046

This PR is to add a `headerHeight` property to `SearchAnchor` and `SearchViewThemeData` so the header height on the search view can be customized.
parent a3c11cdc
...@@ -123,6 +123,7 @@ class SearchAnchor extends StatefulWidget { ...@@ -123,6 +123,7 @@ class SearchAnchor extends StatefulWidget {
this.viewSurfaceTintColor, this.viewSurfaceTintColor,
this.viewSide, this.viewSide,
this.viewShape, this.viewShape,
this.headerHeight,
this.headerTextStyle, this.headerTextStyle,
this.headerHintStyle, this.headerHintStyle,
this.dividerColor, this.dividerColor,
...@@ -169,6 +170,7 @@ class SearchAnchor extends StatefulWidget { ...@@ -169,6 +170,7 @@ class SearchAnchor extends StatefulWidget {
double? viewElevation, double? viewElevation,
BorderSide? viewSide, BorderSide? viewSide,
OutlinedBorder? viewShape, OutlinedBorder? viewShape,
double? viewHeaderHeight,
TextStyle? viewHeaderTextStyle, TextStyle? viewHeaderTextStyle,
TextStyle? viewHeaderHintStyle, TextStyle? viewHeaderHintStyle,
Color? dividerColor, Color? dividerColor,
...@@ -261,6 +263,12 @@ class SearchAnchor extends StatefulWidget { ...@@ -261,6 +263,12 @@ class SearchAnchor extends StatefulWidget {
/// mode and a [RoundedRectangleBorder] shape with a 28.0 radius otherwise. /// mode and a [RoundedRectangleBorder] shape with a 28.0 radius otherwise.
final OutlinedBorder? viewShape; final OutlinedBorder? viewShape;
/// The height of the search field on the search view.
///
/// If null, the value of [SearchViewThemeData.headerHeight] will be used. If
/// this is also null, the default value is 56.0.
final double? headerHeight;
/// The style to use for the text being edited on the search view. /// The style to use for the text being edited on the search view.
/// ///
/// If null, defaults to the `bodyLarge` text style from the current [Theme]. /// If null, defaults to the `bodyLarge` text style from the current [Theme].
...@@ -396,6 +404,7 @@ class _SearchAnchorState extends State<SearchAnchor> { ...@@ -396,6 +404,7 @@ class _SearchAnchorState extends State<SearchAnchor> {
viewSurfaceTintColor: widget.viewSurfaceTintColor, viewSurfaceTintColor: widget.viewSurfaceTintColor,
viewSide: widget.viewSide, viewSide: widget.viewSide,
viewShape: widget.viewShape, viewShape: widget.viewShape,
viewHeaderHeight: widget.headerHeight,
viewHeaderTextStyle: widget.headerTextStyle, viewHeaderTextStyle: widget.headerTextStyle,
viewHeaderHintStyle: widget.headerHintStyle, viewHeaderHintStyle: widget.headerHintStyle,
dividerColor: widget.dividerColor, dividerColor: widget.dividerColor,
...@@ -474,6 +483,7 @@ class _SearchViewRoute extends PopupRoute<_SearchViewRoute> { ...@@ -474,6 +483,7 @@ class _SearchViewRoute extends PopupRoute<_SearchViewRoute> {
this.viewSurfaceTintColor, this.viewSurfaceTintColor,
this.viewSide, this.viewSide,
this.viewShape, this.viewShape,
this.viewHeaderHeight,
this.viewHeaderTextStyle, this.viewHeaderTextStyle,
this.viewHeaderHintStyle, this.viewHeaderHintStyle,
this.dividerColor, this.dividerColor,
...@@ -501,6 +511,7 @@ class _SearchViewRoute extends PopupRoute<_SearchViewRoute> { ...@@ -501,6 +511,7 @@ class _SearchViewRoute extends PopupRoute<_SearchViewRoute> {
final Color? viewSurfaceTintColor; final Color? viewSurfaceTintColor;
final BorderSide? viewSide; final BorderSide? viewSide;
final OutlinedBorder? viewShape; final OutlinedBorder? viewShape;
final double? viewHeaderHeight;
final TextStyle? viewHeaderTextStyle; final TextStyle? viewHeaderTextStyle;
final TextStyle? viewHeaderHintStyle; final TextStyle? viewHeaderHintStyle;
final Color? dividerColor; final Color? dividerColor;
...@@ -644,6 +655,7 @@ class _SearchViewRoute extends PopupRoute<_SearchViewRoute> { ...@@ -644,6 +655,7 @@ class _SearchViewRoute extends PopupRoute<_SearchViewRoute> {
viewSurfaceTintColor: viewSurfaceTintColor, viewSurfaceTintColor: viewSurfaceTintColor,
viewSide: viewSide, viewSide: viewSide,
viewShape: viewShape, viewShape: viewShape,
viewHeaderHeight: viewHeaderHeight,
viewHeaderTextStyle: viewHeaderTextStyle, viewHeaderTextStyle: viewHeaderTextStyle,
viewHeaderHintStyle: viewHeaderHintStyle, viewHeaderHintStyle: viewHeaderHintStyle,
dividerColor: dividerColor, dividerColor: dividerColor,
...@@ -683,6 +695,7 @@ class _ViewContent extends StatefulWidget { ...@@ -683,6 +695,7 @@ class _ViewContent extends StatefulWidget {
this.viewSurfaceTintColor, this.viewSurfaceTintColor,
this.viewSide, this.viewSide,
this.viewShape, this.viewShape,
this.viewHeaderHeight,
this.viewHeaderTextStyle, this.viewHeaderTextStyle,
this.viewHeaderHintStyle, this.viewHeaderHintStyle,
this.dividerColor, this.dividerColor,
...@@ -709,6 +722,7 @@ class _ViewContent extends StatefulWidget { ...@@ -709,6 +722,7 @@ class _ViewContent extends StatefulWidget {
final Color? viewSurfaceTintColor; final Color? viewSurfaceTintColor;
final BorderSide? viewSide; final BorderSide? viewSide;
final OutlinedBorder? viewShape; final OutlinedBorder? viewShape;
final double? viewHeaderHeight;
final TextStyle? viewHeaderTextStyle; final TextStyle? viewHeaderTextStyle;
final TextStyle? viewHeaderHintStyle; final TextStyle? viewHeaderHintStyle;
final Color? dividerColor; final Color? dividerColor;
...@@ -836,6 +850,10 @@ class _ViewContentState extends State<_ViewContent> { ...@@ -836,6 +850,10 @@ class _ViewContentState extends State<_ViewContent> {
?? viewTheme.dividerColor ?? viewTheme.dividerColor
?? dividerTheme.color ?? dividerTheme.color
?? viewDefaults.dividerColor!; ?? viewDefaults.dividerColor!;
final double? effectiveHeaderHeight = widget.viewHeaderHeight ?? viewTheme.headerHeight;
final BoxConstraints? headerConstraints = effectiveHeaderHeight == null
? null
: BoxConstraints.tightFor(height: effectiveHeaderHeight);
final TextStyle? effectiveTextStyle = widget.viewHeaderTextStyle final TextStyle? effectiveTextStyle = widget.viewHeaderTextStyle
?? viewTheme.headerTextStyle ?? viewTheme.headerTextStyle
?? viewDefaults.headerTextStyle; ?? viewDefaults.headerTextStyle;
...@@ -885,7 +903,7 @@ class _ViewContentState extends State<_ViewContent> { ...@@ -885,7 +903,7 @@ class _ViewContentState extends State<_ViewContent> {
bottom: false, bottom: false,
child: SearchBar( child: SearchBar(
autoFocus: true, autoFocus: true,
constraints: widget.showFullScreenView ? BoxConstraints(minHeight: _SearchViewDefaultsM3.fullScreenBarHeight) : null, constraints: headerConstraints ?? (widget.showFullScreenView ? BoxConstraints(minHeight: _SearchViewDefaultsM3.fullScreenBarHeight) : null),
leading: widget.viewLeading ?? defaultLeading, leading: widget.viewLeading ?? defaultLeading,
trailing: widget.viewTrailing ?? defaultTrailing, trailing: widget.viewTrailing ?? defaultTrailing,
hintText: widget.viewHintText, hintText: widget.viewHintText,
...@@ -956,6 +974,7 @@ class _SearchAnchorWithSearchBar extends SearchAnchor { ...@@ -956,6 +974,7 @@ class _SearchAnchorWithSearchBar extends SearchAnchor {
super.viewElevation, super.viewElevation,
super.viewSide, super.viewSide,
super.viewShape, super.viewShape,
double? viewHeaderHeight,
TextStyle? viewHeaderTextStyle, TextStyle? viewHeaderTextStyle,
TextStyle? viewHeaderHintStyle, TextStyle? viewHeaderHintStyle,
super.dividerColor, super.dividerColor,
...@@ -971,6 +990,7 @@ class _SearchAnchorWithSearchBar extends SearchAnchor { ...@@ -971,6 +990,7 @@ class _SearchAnchorWithSearchBar extends SearchAnchor {
super.keyboardType, super.keyboardType,
}) : super( }) : super(
viewHintText: viewHintText ?? barHintText, viewHintText: viewHintText ?? barHintText,
headerHeight: viewHeaderHeight,
headerTextStyle: viewHeaderTextStyle, headerTextStyle: viewHeaderTextStyle,
headerHintStyle: viewHeaderHintStyle, headerHintStyle: viewHeaderHintStyle,
viewOnSubmitted: onSubmitted, viewOnSubmitted: onSubmitted,
......
...@@ -42,6 +42,7 @@ class SearchViewThemeData with Diagnosticable { ...@@ -42,6 +42,7 @@ class SearchViewThemeData with Diagnosticable {
this.constraints, this.constraints,
this.side, this.side,
this.shape, this.shape,
this.headerHeight,
this.headerTextStyle, this.headerTextStyle,
this.headerHintStyle, this.headerHintStyle,
this.dividerColor, this.dividerColor,
...@@ -62,6 +63,9 @@ class SearchViewThemeData with Diagnosticable { ...@@ -62,6 +63,9 @@ class SearchViewThemeData with Diagnosticable {
/// Overrides the default value of the [SearchAnchor.viewShape]. /// Overrides the default value of the [SearchAnchor.viewShape].
final OutlinedBorder? shape; final OutlinedBorder? shape;
/// Overrides the default value of the [SearchAnchor.headerHeight].
final double? headerHeight;
/// Overrides the default value for [SearchAnchor.headerTextStyle]. /// Overrides the default value for [SearchAnchor.headerTextStyle].
final TextStyle? headerTextStyle; final TextStyle? headerTextStyle;
...@@ -82,6 +86,7 @@ class SearchViewThemeData with Diagnosticable { ...@@ -82,6 +86,7 @@ class SearchViewThemeData with Diagnosticable {
Color? surfaceTintColor, Color? surfaceTintColor,
BorderSide? side, BorderSide? side,
OutlinedBorder? shape, OutlinedBorder? shape,
double? headerHeight,
TextStyle? headerTextStyle, TextStyle? headerTextStyle,
TextStyle? headerHintStyle, TextStyle? headerHintStyle,
BoxConstraints? constraints, BoxConstraints? constraints,
...@@ -93,6 +98,7 @@ class SearchViewThemeData with Diagnosticable { ...@@ -93,6 +98,7 @@ class SearchViewThemeData with Diagnosticable {
surfaceTintColor: surfaceTintColor ?? this.surfaceTintColor, surfaceTintColor: surfaceTintColor ?? this.surfaceTintColor,
side: side ?? this.side, side: side ?? this.side,
shape: shape ?? this.shape, shape: shape ?? this.shape,
headerHeight: headerHeight ?? this.headerHeight,
headerTextStyle: headerTextStyle ?? this.headerTextStyle, headerTextStyle: headerTextStyle ?? this.headerTextStyle,
headerHintStyle: headerHintStyle ?? this.headerHintStyle, headerHintStyle: headerHintStyle ?? this.headerHintStyle,
constraints: constraints ?? this.constraints, constraints: constraints ?? this.constraints,
...@@ -111,6 +117,7 @@ class SearchViewThemeData with Diagnosticable { ...@@ -111,6 +117,7 @@ class SearchViewThemeData with Diagnosticable {
surfaceTintColor: Color.lerp(a?.surfaceTintColor, b?.surfaceTintColor, t), surfaceTintColor: Color.lerp(a?.surfaceTintColor, b?.surfaceTintColor, t),
side: _lerpSides(a?.side, b?.side, t), side: _lerpSides(a?.side, b?.side, t),
shape: OutlinedBorder.lerp(a?.shape, b?.shape, t), shape: OutlinedBorder.lerp(a?.shape, b?.shape, t),
headerHeight: lerpDouble(a?.headerHeight, b?.headerHeight, t),
headerTextStyle: TextStyle.lerp(a?.headerTextStyle, b?.headerTextStyle, t), headerTextStyle: TextStyle.lerp(a?.headerTextStyle, b?.headerTextStyle, t),
headerHintStyle: TextStyle.lerp(a?.headerTextStyle, b?.headerTextStyle, t), headerHintStyle: TextStyle.lerp(a?.headerTextStyle, b?.headerTextStyle, t),
constraints: BoxConstraints.lerp(a?.constraints, b?.constraints, t), constraints: BoxConstraints.lerp(a?.constraints, b?.constraints, t),
...@@ -125,6 +132,7 @@ class SearchViewThemeData with Diagnosticable { ...@@ -125,6 +132,7 @@ class SearchViewThemeData with Diagnosticable {
surfaceTintColor, surfaceTintColor,
side, side,
shape, shape,
headerHeight,
headerTextStyle, headerTextStyle,
headerHintStyle, headerHintStyle,
constraints, constraints,
...@@ -145,6 +153,7 @@ class SearchViewThemeData with Diagnosticable { ...@@ -145,6 +153,7 @@ class SearchViewThemeData with Diagnosticable {
&& other.surfaceTintColor == surfaceTintColor && other.surfaceTintColor == surfaceTintColor
&& other.side == side && other.side == side
&& other.shape == shape && other.shape == shape
&& other.headerHeight == headerHeight
&& other.headerTextStyle == headerTextStyle && other.headerTextStyle == headerTextStyle
&& other.headerHintStyle == headerHintStyle && other.headerHintStyle == headerHintStyle
&& other.constraints == constraints && other.constraints == constraints
...@@ -159,6 +168,7 @@ class SearchViewThemeData with Diagnosticable { ...@@ -159,6 +168,7 @@ class SearchViewThemeData with Diagnosticable {
properties.add(DiagnosticsProperty<Color?>('surfaceTintColor', surfaceTintColor, defaultValue: null)); properties.add(DiagnosticsProperty<Color?>('surfaceTintColor', surfaceTintColor, defaultValue: null));
properties.add(DiagnosticsProperty<BorderSide?>('side', side, defaultValue: null)); properties.add(DiagnosticsProperty<BorderSide?>('side', side, defaultValue: null));
properties.add(DiagnosticsProperty<OutlinedBorder?>('shape', shape, defaultValue: null)); properties.add(DiagnosticsProperty<OutlinedBorder?>('shape', shape, defaultValue: null));
properties.add(DiagnosticsProperty<double?>('headerHeight', headerHeight, defaultValue: null));
properties.add(DiagnosticsProperty<TextStyle?>('headerTextStyle', headerTextStyle, defaultValue: null)); properties.add(DiagnosticsProperty<TextStyle?>('headerTextStyle', headerTextStyle, defaultValue: null));
properties.add(DiagnosticsProperty<TextStyle?>('headerHintStyle', headerHintStyle, defaultValue: null)); properties.add(DiagnosticsProperty<TextStyle?>('headerHintStyle', headerHintStyle, defaultValue: null));
properties.add(DiagnosticsProperty<BoxConstraints>('constraints', constraints, defaultValue: null)); properties.add(DiagnosticsProperty<BoxConstraints>('constraints', constraints, defaultValue: null));
......
...@@ -3016,6 +3016,52 @@ void main() { ...@@ -3016,6 +3016,52 @@ void main() {
final Opacity opacityWidget = tester.widget<Opacity>(opacityFinder); final Opacity opacityWidget = tester.widget<Opacity>(opacityFinder);
expect(opacityWidget.opacity, 0.38); expect(opacityWidget.opacity, 0.38);
}); });
testWidgets('SearchAnchor respects headerHeight', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
home: Center(
child: Material(
child: SearchAnchor(
isFullScreen: true,
builder: (BuildContext context, SearchController controller) {
return const Icon(Icons.search);
},
headerHeight: 32,
suggestionsBuilder: (BuildContext context, SearchController controller) {
return <Widget>[];
},
),
),
),
));
await tester.pump();
await tester.tap(find.byIcon(Icons.search)); // Open search view.
await tester.pumpAndSettle();
final Finder findHeader = find.descendant(of: findViewContent(), matching: find.byType(SearchBar));
expect(tester.getSize(findHeader).height, 32);
});
testWidgets('SearchAnchor.bar respects viewHeaderHeight', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
home: Center(
child: Material(
child: SearchAnchor.bar(
isFullScreen: true,
viewHeaderHeight: 32,
suggestionsBuilder: (BuildContext context, SearchController controller) {
return <Widget>[];
},
),
),
),
));
await tester.pump();
await tester.tap(find.byType(SearchBar)); // Open search view.
await tester.pumpAndSettle();
final Finder findHeader = find.descendant(of: findViewContent(), matching: find.byType(SearchBar));
final RenderBox box = tester.renderObject(findHeader);
expect(box.size.height, 32);
});
} }
Future<void> checkSearchBarDefaults(WidgetTester tester, ColorScheme colorScheme, Material material) async { Future<void> checkSearchBarDefaults(WidgetTester tester, ColorScheme colorScheme, Material material) async {
......
...@@ -28,6 +28,7 @@ void main() { ...@@ -28,6 +28,7 @@ void main() {
expect(themeData.constraints, null); expect(themeData.constraints, null);
expect(themeData.side, null); expect(themeData.side, null);
expect(themeData.shape, null); expect(themeData.shape, null);
expect(themeData.headerHeight, null);
expect(themeData.headerTextStyle, null); expect(themeData.headerTextStyle, null);
expect(themeData.headerHintStyle, null); expect(themeData.headerHintStyle, null);
expect(themeData.dividerColor, null); expect(themeData.dividerColor, null);
...@@ -39,6 +40,7 @@ void main() { ...@@ -39,6 +40,7 @@ void main() {
expect(theme.data.constraints, null); expect(theme.data.constraints, null);
expect(theme.data.side, null); expect(theme.data.side, null);
expect(theme.data.shape, null); expect(theme.data.shape, null);
expect(theme.data.headerHeight, null);
expect(theme.data.headerTextStyle, null); expect(theme.data.headerTextStyle, null);
expect(theme.data.headerHintStyle, null); expect(theme.data.headerHintStyle, null);
expect(theme.data.dividerColor, null); expect(theme.data.dividerColor, null);
...@@ -65,6 +67,7 @@ void main() { ...@@ -65,6 +67,7 @@ void main() {
surfaceTintColor: Color(0xfffffff3), surfaceTintColor: Color(0xfffffff3),
side: BorderSide(width: 2.5, color: Color(0xfffffff5)), side: BorderSide(width: 2.5, color: Color(0xfffffff5)),
shape: RoundedRectangleBorder(), shape: RoundedRectangleBorder(),
headerHeight: 35.5,
headerTextStyle: TextStyle(fontSize: 24.0), headerTextStyle: TextStyle(fontSize: 24.0),
headerHintStyle: TextStyle(fontSize: 16.0), headerHintStyle: TextStyle(fontSize: 16.0),
constraints: BoxConstraints(minWidth: 350, minHeight: 240), constraints: BoxConstraints(minWidth: 350, minHeight: 240),
...@@ -80,9 +83,10 @@ void main() { ...@@ -80,9 +83,10 @@ void main() {
expect(description[2], 'surfaceTintColor: Color(0xfffffff3)'); expect(description[2], 'surfaceTintColor: Color(0xfffffff3)');
expect(description[3], 'side: BorderSide(color: Color(0xfffffff5), width: 2.5)'); expect(description[3], 'side: BorderSide(color: Color(0xfffffff5), width: 2.5)');
expect(description[4], 'shape: RoundedRectangleBorder(BorderSide(width: 0.0, style: none), BorderRadius.zero)'); expect(description[4], 'shape: RoundedRectangleBorder(BorderSide(width: 0.0, style: none), BorderRadius.zero)');
expect(description[5], 'headerTextStyle: TextStyle(inherit: true, size: 24.0)'); expect(description[5], 'headerHeight: 35.5');
expect(description[6], 'headerHintStyle: TextStyle(inherit: true, size: 16.0)'); expect(description[6], 'headerTextStyle: TextStyle(inherit: true, size: 24.0)');
expect(description[7], 'constraints: BoxConstraints(350.0<=w<=Infinity, 240.0<=h<=Infinity)'); expect(description[7], 'headerHintStyle: TextStyle(inherit: true, size: 16.0)');
expect(description[8], 'constraints: BoxConstraints(350.0<=w<=Infinity, 240.0<=h<=Infinity)');
}); });
group('[Theme, SearchViewTheme, SearchView properties overrides]', () { group('[Theme, SearchViewTheme, SearchView properties overrides]', () {
...@@ -91,6 +95,7 @@ void main() { ...@@ -91,6 +95,7 @@ void main() {
const Color surfaceTintColor = Color(0xff000002); const Color surfaceTintColor = Color(0xff000002);
const BorderSide side = BorderSide(color: Color(0xff000003), width: 2.0); const BorderSide side = BorderSide(color: Color(0xff000003), width: 2.0);
const OutlinedBorder shape = RoundedRectangleBorder(side: side, borderRadius: BorderRadius.all(Radius.circular(20.0))); const OutlinedBorder shape = RoundedRectangleBorder(side: side, borderRadius: BorderRadius.all(Radius.circular(20.0)));
const double headerHeight = 45.0;
const TextStyle headerTextStyle = TextStyle(color: Color(0xff000004), fontSize: 20.0); const TextStyle headerTextStyle = TextStyle(color: Color(0xff000004), fontSize: 20.0);
const TextStyle headerHintStyle = TextStyle(color: Color(0xff000005), fontSize: 18.0); const TextStyle headerHintStyle = TextStyle(color: Color(0xff000005), fontSize: 18.0);
const BoxConstraints constraints = BoxConstraints(minWidth: 250.0, maxWidth: 300.0, minHeight: 450.0); const BoxConstraints constraints = BoxConstraints(minWidth: 250.0, maxWidth: 300.0, minHeight: 450.0);
...@@ -101,6 +106,7 @@ void main() { ...@@ -101,6 +106,7 @@ void main() {
surfaceTintColor: surfaceTintColor, surfaceTintColor: surfaceTintColor,
side: side, side: side,
shape: shape, shape: shape,
headerHeight: headerHeight,
headerTextStyle: headerTextStyle, headerTextStyle: headerTextStyle,
headerHintStyle: headerHintStyle, headerHintStyle: headerHintStyle,
constraints: constraints, constraints: constraints,
...@@ -139,6 +145,7 @@ void main() { ...@@ -139,6 +145,7 @@ void main() {
viewSurfaceTintColor: surfaceTintColor, viewSurfaceTintColor: surfaceTintColor,
viewSide: side, viewSide: side,
viewShape: shape, viewShape: shape,
headerHeight: headerHeight,
headerTextStyle: headerTextStyle, headerTextStyle: headerTextStyle,
headerHintStyle: headerHintStyle, headerHintStyle: headerHintStyle,
viewConstraints: constraints, viewConstraints: constraints,
...@@ -189,6 +196,8 @@ void main() { ...@@ -189,6 +196,8 @@ void main() {
expect(hintText.style?.color, headerHintStyle.color); expect(hintText.style?.color, headerHintStyle.color);
expect(hintText.style?.fontSize, headerHintStyle.fontSize); expect(hintText.style?.fontSize, headerHintStyle.fontSize);
final RenderBox box = tester.renderObject(find.descendant(of: findViewContent(), matching: find.byType(SearchBar)));
expect(box.size.height, headerHeight);
await tester.enterText(find.byType(TextField), 'input'); await tester.enterText(find.byType(TextField), 'input');
final EditableText inputText = tester.widget(find.text('input')); final EditableText inputText = tester.widget(find.text('input'));
expect(inputText.style.color, headerTextStyle.color); expect(inputText.style.color, headerTextStyle.color);
......
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