mirror of
https://github.com/flutter/flutter
synced 2024-08-27 12:00:58 +00:00
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.
This commit is contained in:
parent
a3c11cdc66
commit
ef794e2a28
|
@ -123,6 +123,7 @@ class SearchAnchor extends StatefulWidget {
|
|||
this.viewSurfaceTintColor,
|
||||
this.viewSide,
|
||||
this.viewShape,
|
||||
this.headerHeight,
|
||||
this.headerTextStyle,
|
||||
this.headerHintStyle,
|
||||
this.dividerColor,
|
||||
|
@ -169,6 +170,7 @@ class SearchAnchor extends StatefulWidget {
|
|||
double? viewElevation,
|
||||
BorderSide? viewSide,
|
||||
OutlinedBorder? viewShape,
|
||||
double? viewHeaderHeight,
|
||||
TextStyle? viewHeaderTextStyle,
|
||||
TextStyle? viewHeaderHintStyle,
|
||||
Color? dividerColor,
|
||||
|
@ -261,6 +263,12 @@ class SearchAnchor extends StatefulWidget {
|
|||
/// mode and a [RoundedRectangleBorder] shape with a 28.0 radius otherwise.
|
||||
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.
|
||||
///
|
||||
/// If null, defaults to the `bodyLarge` text style from the current [Theme].
|
||||
|
@ -396,6 +404,7 @@ class _SearchAnchorState extends State<SearchAnchor> {
|
|||
viewSurfaceTintColor: widget.viewSurfaceTintColor,
|
||||
viewSide: widget.viewSide,
|
||||
viewShape: widget.viewShape,
|
||||
viewHeaderHeight: widget.headerHeight,
|
||||
viewHeaderTextStyle: widget.headerTextStyle,
|
||||
viewHeaderHintStyle: widget.headerHintStyle,
|
||||
dividerColor: widget.dividerColor,
|
||||
|
@ -474,6 +483,7 @@ class _SearchViewRoute extends PopupRoute<_SearchViewRoute> {
|
|||
this.viewSurfaceTintColor,
|
||||
this.viewSide,
|
||||
this.viewShape,
|
||||
this.viewHeaderHeight,
|
||||
this.viewHeaderTextStyle,
|
||||
this.viewHeaderHintStyle,
|
||||
this.dividerColor,
|
||||
|
@ -501,6 +511,7 @@ class _SearchViewRoute extends PopupRoute<_SearchViewRoute> {
|
|||
final Color? viewSurfaceTintColor;
|
||||
final BorderSide? viewSide;
|
||||
final OutlinedBorder? viewShape;
|
||||
final double? viewHeaderHeight;
|
||||
final TextStyle? viewHeaderTextStyle;
|
||||
final TextStyle? viewHeaderHintStyle;
|
||||
final Color? dividerColor;
|
||||
|
@ -644,6 +655,7 @@ class _SearchViewRoute extends PopupRoute<_SearchViewRoute> {
|
|||
viewSurfaceTintColor: viewSurfaceTintColor,
|
||||
viewSide: viewSide,
|
||||
viewShape: viewShape,
|
||||
viewHeaderHeight: viewHeaderHeight,
|
||||
viewHeaderTextStyle: viewHeaderTextStyle,
|
||||
viewHeaderHintStyle: viewHeaderHintStyle,
|
||||
dividerColor: dividerColor,
|
||||
|
@ -683,6 +695,7 @@ class _ViewContent extends StatefulWidget {
|
|||
this.viewSurfaceTintColor,
|
||||
this.viewSide,
|
||||
this.viewShape,
|
||||
this.viewHeaderHeight,
|
||||
this.viewHeaderTextStyle,
|
||||
this.viewHeaderHintStyle,
|
||||
this.dividerColor,
|
||||
|
@ -709,6 +722,7 @@ class _ViewContent extends StatefulWidget {
|
|||
final Color? viewSurfaceTintColor;
|
||||
final BorderSide? viewSide;
|
||||
final OutlinedBorder? viewShape;
|
||||
final double? viewHeaderHeight;
|
||||
final TextStyle? viewHeaderTextStyle;
|
||||
final TextStyle? viewHeaderHintStyle;
|
||||
final Color? dividerColor;
|
||||
|
@ -836,6 +850,10 @@ class _ViewContentState extends State<_ViewContent> {
|
|||
?? viewTheme.dividerColor
|
||||
?? dividerTheme.color
|
||||
?? viewDefaults.dividerColor!;
|
||||
final double? effectiveHeaderHeight = widget.viewHeaderHeight ?? viewTheme.headerHeight;
|
||||
final BoxConstraints? headerConstraints = effectiveHeaderHeight == null
|
||||
? null
|
||||
: BoxConstraints.tightFor(height: effectiveHeaderHeight);
|
||||
final TextStyle? effectiveTextStyle = widget.viewHeaderTextStyle
|
||||
?? viewTheme.headerTextStyle
|
||||
?? viewDefaults.headerTextStyle;
|
||||
|
@ -885,7 +903,7 @@ class _ViewContentState extends State<_ViewContent> {
|
|||
bottom: false,
|
||||
child: SearchBar(
|
||||
autoFocus: true,
|
||||
constraints: widget.showFullScreenView ? BoxConstraints(minHeight: _SearchViewDefaultsM3.fullScreenBarHeight) : null,
|
||||
constraints: headerConstraints ?? (widget.showFullScreenView ? BoxConstraints(minHeight: _SearchViewDefaultsM3.fullScreenBarHeight) : null),
|
||||
leading: widget.viewLeading ?? defaultLeading,
|
||||
trailing: widget.viewTrailing ?? defaultTrailing,
|
||||
hintText: widget.viewHintText,
|
||||
|
@ -956,6 +974,7 @@ class _SearchAnchorWithSearchBar extends SearchAnchor {
|
|||
super.viewElevation,
|
||||
super.viewSide,
|
||||
super.viewShape,
|
||||
double? viewHeaderHeight,
|
||||
TextStyle? viewHeaderTextStyle,
|
||||
TextStyle? viewHeaderHintStyle,
|
||||
super.dividerColor,
|
||||
|
@ -971,6 +990,7 @@ class _SearchAnchorWithSearchBar extends SearchAnchor {
|
|||
super.keyboardType,
|
||||
}) : super(
|
||||
viewHintText: viewHintText ?? barHintText,
|
||||
headerHeight: viewHeaderHeight,
|
||||
headerTextStyle: viewHeaderTextStyle,
|
||||
headerHintStyle: viewHeaderHintStyle,
|
||||
viewOnSubmitted: onSubmitted,
|
||||
|
|
|
@ -42,6 +42,7 @@ class SearchViewThemeData with Diagnosticable {
|
|||
this.constraints,
|
||||
this.side,
|
||||
this.shape,
|
||||
this.headerHeight,
|
||||
this.headerTextStyle,
|
||||
this.headerHintStyle,
|
||||
this.dividerColor,
|
||||
|
@ -62,6 +63,9 @@ class SearchViewThemeData with Diagnosticable {
|
|||
/// Overrides the default value of the [SearchAnchor.viewShape].
|
||||
final OutlinedBorder? shape;
|
||||
|
||||
/// Overrides the default value of the [SearchAnchor.headerHeight].
|
||||
final double? headerHeight;
|
||||
|
||||
/// Overrides the default value for [SearchAnchor.headerTextStyle].
|
||||
final TextStyle? headerTextStyle;
|
||||
|
||||
|
@ -82,6 +86,7 @@ class SearchViewThemeData with Diagnosticable {
|
|||
Color? surfaceTintColor,
|
||||
BorderSide? side,
|
||||
OutlinedBorder? shape,
|
||||
double? headerHeight,
|
||||
TextStyle? headerTextStyle,
|
||||
TextStyle? headerHintStyle,
|
||||
BoxConstraints? constraints,
|
||||
|
@ -93,6 +98,7 @@ class SearchViewThemeData with Diagnosticable {
|
|||
surfaceTintColor: surfaceTintColor ?? this.surfaceTintColor,
|
||||
side: side ?? this.side,
|
||||
shape: shape ?? this.shape,
|
||||
headerHeight: headerHeight ?? this.headerHeight,
|
||||
headerTextStyle: headerTextStyle ?? this.headerTextStyle,
|
||||
headerHintStyle: headerHintStyle ?? this.headerHintStyle,
|
||||
constraints: constraints ?? this.constraints,
|
||||
|
@ -111,6 +117,7 @@ class SearchViewThemeData with Diagnosticable {
|
|||
surfaceTintColor: Color.lerp(a?.surfaceTintColor, b?.surfaceTintColor, t),
|
||||
side: _lerpSides(a?.side, b?.side, t),
|
||||
shape: OutlinedBorder.lerp(a?.shape, b?.shape, t),
|
||||
headerHeight: lerpDouble(a?.headerHeight, b?.headerHeight, t),
|
||||
headerTextStyle: TextStyle.lerp(a?.headerTextStyle, b?.headerTextStyle, t),
|
||||
headerHintStyle: TextStyle.lerp(a?.headerTextStyle, b?.headerTextStyle, t),
|
||||
constraints: BoxConstraints.lerp(a?.constraints, b?.constraints, t),
|
||||
|
@ -125,6 +132,7 @@ class SearchViewThemeData with Diagnosticable {
|
|||
surfaceTintColor,
|
||||
side,
|
||||
shape,
|
||||
headerHeight,
|
||||
headerTextStyle,
|
||||
headerHintStyle,
|
||||
constraints,
|
||||
|
@ -145,6 +153,7 @@ class SearchViewThemeData with Diagnosticable {
|
|||
&& other.surfaceTintColor == surfaceTintColor
|
||||
&& other.side == side
|
||||
&& other.shape == shape
|
||||
&& other.headerHeight == headerHeight
|
||||
&& other.headerTextStyle == headerTextStyle
|
||||
&& other.headerHintStyle == headerHintStyle
|
||||
&& other.constraints == constraints
|
||||
|
@ -159,6 +168,7 @@ class SearchViewThemeData with Diagnosticable {
|
|||
properties.add(DiagnosticsProperty<Color?>('surfaceTintColor', surfaceTintColor, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<BorderSide?>('side', side, 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?>('headerHintStyle', headerHintStyle, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<BoxConstraints>('constraints', constraints, defaultValue: null));
|
||||
|
|
|
@ -3016,6 +3016,52 @@ void main() {
|
|||
final Opacity opacityWidget = tester.widget<Opacity>(opacityFinder);
|
||||
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 {
|
||||
|
|
|
@ -28,6 +28,7 @@ void main() {
|
|||
expect(themeData.constraints, null);
|
||||
expect(themeData.side, null);
|
||||
expect(themeData.shape, null);
|
||||
expect(themeData.headerHeight, null);
|
||||
expect(themeData.headerTextStyle, null);
|
||||
expect(themeData.headerHintStyle, null);
|
||||
expect(themeData.dividerColor, null);
|
||||
|
@ -39,6 +40,7 @@ void main() {
|
|||
expect(theme.data.constraints, null);
|
||||
expect(theme.data.side, null);
|
||||
expect(theme.data.shape, null);
|
||||
expect(theme.data.headerHeight, null);
|
||||
expect(theme.data.headerTextStyle, null);
|
||||
expect(theme.data.headerHintStyle, null);
|
||||
expect(theme.data.dividerColor, null);
|
||||
|
@ -65,6 +67,7 @@ void main() {
|
|||
surfaceTintColor: Color(0xfffffff3),
|
||||
side: BorderSide(width: 2.5, color: Color(0xfffffff5)),
|
||||
shape: RoundedRectangleBorder(),
|
||||
headerHeight: 35.5,
|
||||
headerTextStyle: TextStyle(fontSize: 24.0),
|
||||
headerHintStyle: TextStyle(fontSize: 16.0),
|
||||
constraints: BoxConstraints(minWidth: 350, minHeight: 240),
|
||||
|
@ -80,9 +83,10 @@ void main() {
|
|||
expect(description[2], 'surfaceTintColor: Color(0xfffffff3)');
|
||||
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[5], 'headerTextStyle: TextStyle(inherit: true, size: 24.0)');
|
||||
expect(description[6], 'headerHintStyle: TextStyle(inherit: true, size: 16.0)');
|
||||
expect(description[7], 'constraints: BoxConstraints(350.0<=w<=Infinity, 240.0<=h<=Infinity)');
|
||||
expect(description[5], 'headerHeight: 35.5');
|
||||
expect(description[6], 'headerTextStyle: TextStyle(inherit: true, size: 24.0)');
|
||||
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]', () {
|
||||
|
@ -91,6 +95,7 @@ void main() {
|
|||
const Color surfaceTintColor = Color(0xff000002);
|
||||
const BorderSide side = BorderSide(color: Color(0xff000003), width: 2.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 headerHintStyle = TextStyle(color: Color(0xff000005), fontSize: 18.0);
|
||||
const BoxConstraints constraints = BoxConstraints(minWidth: 250.0, maxWidth: 300.0, minHeight: 450.0);
|
||||
|
@ -101,6 +106,7 @@ void main() {
|
|||
surfaceTintColor: surfaceTintColor,
|
||||
side: side,
|
||||
shape: shape,
|
||||
headerHeight: headerHeight,
|
||||
headerTextStyle: headerTextStyle,
|
||||
headerHintStyle: headerHintStyle,
|
||||
constraints: constraints,
|
||||
|
@ -139,6 +145,7 @@ void main() {
|
|||
viewSurfaceTintColor: surfaceTintColor,
|
||||
viewSide: side,
|
||||
viewShape: shape,
|
||||
headerHeight: headerHeight,
|
||||
headerTextStyle: headerTextStyle,
|
||||
headerHintStyle: headerHintStyle,
|
||||
viewConstraints: constraints,
|
||||
|
@ -189,6 +196,8 @@ void main() {
|
|||
expect(hintText.style?.color, headerHintStyle.color);
|
||||
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');
|
||||
final EditableText inputText = tester.widget(find.text('input'));
|
||||
expect(inputText.style.color, headerTextStyle.color);
|
||||
|
|
Loading…
Reference in a new issue