mirror of
https://github.com/flutter/flutter.git
synced 2026-02-16 07:42:10 +08:00
Added support for AppBarTheme.toolbarHeight (#80467)
This commit is contained in:
parent
2f1d034087
commit
cd4fe85bfa
@ -54,6 +54,14 @@ class _ToolbarContainerLayout extends SingleChildLayoutDelegate {
|
||||
toolbarHeight != oldDelegate.toolbarHeight;
|
||||
}
|
||||
|
||||
class _PreferredAppBarSize extends Size {
|
||||
_PreferredAppBarSize(this.toolbarHeight, this.bottomHeight)
|
||||
: super.fromHeight((toolbarHeight ?? kToolbarHeight) + (bottomHeight ?? 0));
|
||||
|
||||
final double? toolbarHeight;
|
||||
final double? bottomHeight;
|
||||
}
|
||||
|
||||
/// A material design app bar.
|
||||
///
|
||||
/// An app bar consists of a toolbar and potentially other widgets, such as a
|
||||
@ -202,9 +210,21 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget {
|
||||
assert(primary != null),
|
||||
assert(toolbarOpacity != null),
|
||||
assert(bottomOpacity != null),
|
||||
preferredSize = Size.fromHeight(toolbarHeight ?? kToolbarHeight + (bottom?.preferredSize.height ?? 0.0)),
|
||||
preferredSize = _PreferredAppBarSize(toolbarHeight, bottom?.preferredSize.height),
|
||||
super(key: key);
|
||||
|
||||
/// Used by [Scaffold] to compute its [AppBar]'s overall height. The returned value is
|
||||
/// the same `preferredSize.height` unless [AppBar.toolbarHeight] was null and
|
||||
/// `AppBarTheme.of(context).toolbarHeight` is non-null. In that case the
|
||||
/// return value is the sum of the theme's toolbar height and the height of
|
||||
/// the app bar's [AppBar.bottom] widget.
|
||||
static double preferredHeightFor(BuildContext context, Size preferredSize) {
|
||||
if (preferredSize is _PreferredAppBarSize && preferredSize.toolbarHeight == null) {
|
||||
return (AppBarTheme.of(context).toolbarHeight ?? kToolbarHeight) + (preferredSize.bottomHeight ?? 0);
|
||||
}
|
||||
return preferredSize.height;
|
||||
}
|
||||
|
||||
/// {@template flutter.material.appbar.leading}
|
||||
/// A widget to display before the toolbar's [title].
|
||||
///
|
||||
@ -781,7 +801,7 @@ class _AppBarState extends State<AppBar> {
|
||||
final bool canPop = parentRoute?.canPop ?? false;
|
||||
final bool useCloseButton = parentRoute is PageRoute<dynamic> && parentRoute.fullscreenDialog;
|
||||
|
||||
final double toolbarHeight = widget.toolbarHeight ?? kToolbarHeight;
|
||||
final double toolbarHeight = widget.toolbarHeight ?? appBarTheme.toolbarHeight ?? kToolbarHeight;
|
||||
final bool backwardsCompatibility = widget.backwardsCompatibility ?? appBarTheme.backwardsCompatibility ?? true;
|
||||
|
||||
final Color backgroundColor = backwardsCompatibility
|
||||
|
||||
@ -39,6 +39,7 @@ class AppBarTheme with Diagnosticable {
|
||||
this.textTheme,
|
||||
this.centerTitle,
|
||||
this.titleSpacing,
|
||||
this.toolbarHeight,
|
||||
this.toolbarTextStyle,
|
||||
this.titleTextStyle,
|
||||
this.systemOverlayStyle,
|
||||
@ -144,6 +145,15 @@ class AppBarTheme with Diagnosticable {
|
||||
/// If null, [AppBar] uses default value of [NavigationToolbar.kMiddleSpacing].
|
||||
final double? titleSpacing;
|
||||
|
||||
/// Overrides the default value for the [AppBar.toolbarHeight]
|
||||
/// property in all descendant [AppBar] widgets.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [AppBar.preferredHeightFor], which computes the overall
|
||||
/// height of an AppBar widget, taking this value into account.
|
||||
final double? toolbarHeight;
|
||||
|
||||
/// Overrides the default value for the obsolete [AppBar.toolbarTextStyle]
|
||||
/// property in all descendant [AppBar] widgets.
|
||||
///
|
||||
@ -184,6 +194,7 @@ class AppBarTheme with Diagnosticable {
|
||||
TextTheme? textTheme,
|
||||
bool? centerTitle,
|
||||
double? titleSpacing,
|
||||
double? toolbarHeight,
|
||||
TextStyle? toolbarTextStyle,
|
||||
TextStyle? titleTextStyle,
|
||||
SystemUiOverlayStyle? systemOverlayStyle,
|
||||
@ -204,6 +215,7 @@ class AppBarTheme with Diagnosticable {
|
||||
textTheme: textTheme ?? this.textTheme,
|
||||
centerTitle: centerTitle ?? this.centerTitle,
|
||||
titleSpacing: titleSpacing ?? this.titleSpacing,
|
||||
toolbarHeight: toolbarHeight ?? this.toolbarHeight,
|
||||
toolbarTextStyle: toolbarTextStyle ?? this.toolbarTextStyle,
|
||||
titleTextStyle: titleTextStyle ?? this.titleTextStyle,
|
||||
systemOverlayStyle: systemOverlayStyle ?? this.systemOverlayStyle,
|
||||
@ -234,6 +246,7 @@ class AppBarTheme with Diagnosticable {
|
||||
textTheme: TextTheme.lerp(a?.textTheme, b?.textTheme, t),
|
||||
centerTitle: t < 0.5 ? a?.centerTitle : b?.centerTitle,
|
||||
titleSpacing: lerpDouble(a?.titleSpacing, b?.titleSpacing, t),
|
||||
toolbarHeight: lerpDouble(a?.toolbarHeight, b?.toolbarHeight, t),
|
||||
toolbarTextStyle: TextStyle.lerp(a?.toolbarTextStyle, b?.toolbarTextStyle, t),
|
||||
titleTextStyle: TextStyle.lerp(a?.titleTextStyle, b?.titleTextStyle, t),
|
||||
systemOverlayStyle: t < 0.5 ? a?.systemOverlayStyle : b?.systemOverlayStyle,
|
||||
@ -254,6 +267,7 @@ class AppBarTheme with Diagnosticable {
|
||||
textTheme,
|
||||
centerTitle,
|
||||
titleSpacing,
|
||||
toolbarHeight,
|
||||
toolbarTextStyle,
|
||||
titleTextStyle,
|
||||
systemOverlayStyle,
|
||||
@ -278,6 +292,7 @@ class AppBarTheme with Diagnosticable {
|
||||
&& other.textTheme == textTheme
|
||||
&& other.centerTitle == centerTitle
|
||||
&& other.titleSpacing == titleSpacing
|
||||
&& other.toolbarHeight == toolbarHeight
|
||||
&& other.toolbarTextStyle == toolbarTextStyle
|
||||
&& other.titleTextStyle == titleTextStyle
|
||||
&& other.systemOverlayStyle == systemOverlayStyle
|
||||
@ -297,6 +312,7 @@ class AppBarTheme with Diagnosticable {
|
||||
properties.add(DiagnosticsProperty<TextTheme>('textTheme', textTheme, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<bool>('centerTitle', centerTitle, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<double>('titleSpacing', titleSpacing, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<double>('toolbarHeight', toolbarHeight, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<TextStyle>('toolbarTextStyle', toolbarTextStyle, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<TextStyle>('titleTextStyle', titleTextStyle, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<bool>('backwardsCompatibility', backwardsCompatibility, defaultValue: null));
|
||||
|
||||
@ -3035,7 +3035,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin, Resto
|
||||
|
||||
if (widget.appBar != null) {
|
||||
final double topPadding = widget.primary ? mediaQuery.padding.top : 0.0;
|
||||
_appBarMaxHeight = widget.appBar!.preferredSize.height + topPadding;
|
||||
_appBarMaxHeight = AppBar.preferredHeightFor(context, widget.appBar!.preferredSize) + topPadding;
|
||||
assert(_appBarMaxHeight! >= 0.0 && _appBarMaxHeight!.isFinite);
|
||||
_addIfNonNull(
|
||||
children,
|
||||
|
||||
@ -2822,4 +2822,57 @@ void main() {
|
||||
|
||||
expect(tester.takeException(), isNull);
|
||||
});
|
||||
|
||||
testWidgets('AppBar.preferredHeightFor', (WidgetTester tester) async {
|
||||
late double preferredHeight;
|
||||
late Size preferredSize;
|
||||
|
||||
Widget buildFrame({ double? themeToolbarHeight, double? appBarToolbarHeight }) {
|
||||
final AppBar appBar = AppBar(
|
||||
toolbarHeight: appBarToolbarHeight,
|
||||
);
|
||||
return MaterialApp(
|
||||
theme: ThemeData.light().copyWith(
|
||||
appBarTheme: AppBarTheme(
|
||||
toolbarHeight: themeToolbarHeight,
|
||||
),
|
||||
),
|
||||
home: Builder(
|
||||
builder: (BuildContext context) {
|
||||
preferredHeight = AppBar.preferredHeightFor(context, appBar.preferredSize);
|
||||
preferredSize = appBar.preferredSize;
|
||||
return Scaffold(
|
||||
appBar: appBar,
|
||||
body: const Placeholder(),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
await tester.pumpWidget(buildFrame());
|
||||
expect(tester.getSize(find.byType(AppBar)).height, kToolbarHeight);
|
||||
expect(preferredHeight, kToolbarHeight);
|
||||
expect(preferredSize.height, kToolbarHeight);
|
||||
|
||||
await tester.pumpWidget(buildFrame(themeToolbarHeight: 96));
|
||||
await tester.pumpAndSettle(); // Animate MaterialApp theme change.
|
||||
expect(tester.getSize(find.byType(AppBar)).height, 96);
|
||||
expect(preferredHeight, 96);
|
||||
// Special case: AppBarTheme.toolbarHeight specified,
|
||||
// AppBar.theme.toolbarHeight is null.
|
||||
expect(preferredSize.height, kToolbarHeight);
|
||||
|
||||
await tester.pumpWidget(buildFrame(appBarToolbarHeight: 64));
|
||||
await tester.pumpAndSettle(); // Animate MaterialApp theme change.
|
||||
expect(tester.getSize(find.byType(AppBar)).height, 64);
|
||||
expect(preferredHeight, 64);
|
||||
expect(preferredSize.height, 64);
|
||||
|
||||
await tester.pumpWidget(buildFrame(appBarToolbarHeight: 64, themeToolbarHeight: 96));
|
||||
await tester.pumpAndSettle(); // Animate MaterialApp theme change.
|
||||
expect(tester.getSize(find.byType(AppBar)).height, 64);
|
||||
expect(preferredHeight, 64);
|
||||
expect(preferredSize.height, 64);
|
||||
});
|
||||
}
|
||||
|
||||
@ -15,14 +15,18 @@ void main() {
|
||||
});
|
||||
|
||||
testWidgets('Passing no AppBarTheme returns defaults', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(MaterialApp(
|
||||
home: Scaffold(appBar: AppBar(
|
||||
backwardsCompatibility: false,
|
||||
actions: <Widget>[
|
||||
IconButton(icon: const Icon(Icons.share), onPressed: () { }),
|
||||
],
|
||||
)),
|
||||
));
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: Scaffold(
|
||||
appBar: AppBar(
|
||||
backwardsCompatibility: false,
|
||||
actions: <Widget>[
|
||||
IconButton(icon: const Icon(Icons.share), onPressed: () { }),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
final Material widget = _getAppBarMaterial(tester);
|
||||
final IconTheme iconTheme = _getAppBarIconTheme(tester);
|
||||
@ -38,21 +42,27 @@ void main() {
|
||||
expect(actionsIconTheme.data, const IconThemeData(color: Colors.white));
|
||||
expect(actionIconText.text.style!.color, Colors.white);
|
||||
expect(text.style, Typography.material2014().englishLike.bodyText2!.merge(Typography.material2014().white.bodyText2));
|
||||
expect(tester.getSize(find.byType(AppBar)).height, kToolbarHeight);
|
||||
expect(tester.getSize(find.byType(AppBar)).width, 800);
|
||||
});
|
||||
|
||||
testWidgets('AppBar uses values from AppBarTheme', (WidgetTester tester) async {
|
||||
final AppBarTheme appBarTheme = _appBarTheme();
|
||||
|
||||
await tester.pumpWidget(MaterialApp(
|
||||
theme: ThemeData(appBarTheme: appBarTheme),
|
||||
home: Scaffold(appBar: AppBar(
|
||||
backwardsCompatibility: false,
|
||||
title: const Text('App Bar Title'),
|
||||
actions: <Widget>[
|
||||
IconButton(icon: const Icon(Icons.share), onPressed: () { }),
|
||||
],
|
||||
)),
|
||||
));
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData(appBarTheme: appBarTheme),
|
||||
home: Scaffold(
|
||||
appBar: AppBar(
|
||||
backwardsCompatibility: false,
|
||||
title: const Text('App Bar Title'),
|
||||
actions: <Widget>[
|
||||
IconButton(icon: const Icon(Icons.share), onPressed: () { }),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
final Material widget = _getAppBarMaterial(tester);
|
||||
final IconTheme iconTheme = _getAppBarIconTheme(tester);
|
||||
@ -68,6 +78,8 @@ void main() {
|
||||
expect(actionsIconTheme.data, appBarTheme.actionsIconTheme);
|
||||
expect(actionIconText.text.style!.color, appBarTheme.actionsIconTheme!.color);
|
||||
expect(text.style, appBarTheme.toolbarTextStyle);
|
||||
expect(tester.getSize(find.byType(AppBar)).height, appBarTheme.toolbarHeight);
|
||||
expect(tester.getSize(find.byType(AppBar)).width, 800);
|
||||
});
|
||||
|
||||
testWidgets('SliverAppBar allows AppBar to determine backwardsCompatibility', (WidgetTester tester) async {
|
||||
@ -531,6 +543,7 @@ AppBarTheme _appBarTheme() {
|
||||
elevation: elevation,
|
||||
shadowColor: shadowColor,
|
||||
iconTheme: iconThemeData,
|
||||
toolbarHeight: 96,
|
||||
toolbarTextStyle: TextStyle(color: Colors.yellow),
|
||||
titleTextStyle: TextStyle(color: Colors.pink),
|
||||
);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user