Unverified Commit a8f9d4ce authored by Hans Muller's avatar Hans Muller Committed by GitHub

AppBar draws its defaults from theme.colorScheme (#69251)

parent 99e0d3b9
...@@ -11,6 +11,7 @@ import 'package:flutter/widgets.dart'; ...@@ -11,6 +11,7 @@ import 'package:flutter/widgets.dart';
import 'app_bar_theme.dart'; import 'app_bar_theme.dart';
import 'back_button.dart'; import 'back_button.dart';
import 'color_scheme.dart';
import 'constants.dart'; import 'constants.dart';
import 'debug.dart'; import 'debug.dart';
import 'flexible_space_bar.dart'; import 'flexible_space_bar.dart';
...@@ -196,6 +197,7 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget { ...@@ -196,6 +197,7 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget {
this.shadowColor, this.shadowColor,
this.shape, this.shape,
this.backgroundColor, this.backgroundColor,
this.foregroundColor,
this.brightness, this.brightness,
this.iconTheme, this.iconTheme,
this.actionsIconTheme, this.actionsIconTheme,
...@@ -357,20 +359,68 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget { ...@@ -357,20 +359,68 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget {
/// zero. /// zero.
final ShapeBorder? shape; final ShapeBorder? shape;
/// The color to use for the app bar's material. Typically this should be set /// The fill color to use for the app bar's [Material].
/// along with [brightness], [iconTheme], [textTheme].
/// ///
/// If this property is null, then [AppBarTheme.color] of /// If null, then the [AppBarTheme.color] is used. If that value is also
/// [ThemeData.appBarTheme] is used. If that is also null, then /// null, then [AppBar] uses the overall theme's [ColorScheme.primary] if the
/// [ThemeData.primaryColor] is used. /// overall theme's brightness is [Brightness.light], and [ColorScheme.surface]
/// if the overall theme's [brightness] is [Brightness.dark].
///
/// See also:
///
/// * [foregroundColor], which specifies the color for icons and text within
/// the app bar.
/// * [Theme.of], which returns the current overall Material theme as
/// a [ThemeData].
/// * [ThemeData.colorScheme], the thirteen colors that most Material widget
/// default colors are based on.
/// * [ColorScheme.brightness], which indicates if the overall [Theme]
/// is light or dark.
final Color? backgroundColor; final Color? backgroundColor;
/// The brightness of the app bar's material. Typically this is set along /// The default color for [Text] and [Icon]s within the app bar.
/// with [backgroundColor], [iconTheme], [textTheme].
/// ///
/// If this property is null, then [AppBarTheme.brightness] of /// If null, then [AppBarTheme.foregroundColor] is used. If that
/// [ThemeData.appBarTheme] is used. If that is also null, then /// value is also null, then [AppBar] uses the overall theme's
/// [ThemeData.primaryColorBrightness] is used. /// [ColorScheme.onPrimary] if the overall theme's brightness is
/// [Brightness.light], and [ColorScheme.onSurface] if the overall
/// theme's [brightness] is [Brightness.dark].
///
/// This color is used to configure [DefaultTextStyle] that contains
/// the app bar's children, and the default [IconTheme] widgets that
/// are created if [iconTheme] and [actionsIconTheme] are null.
///
/// See also:
///
/// * [backgroundColor], which specifies the app bar's background color.
/// * [Theme.of], which returns the current overall Material theme as
/// a [ThemeData].
/// * [ThemeData.colorScheme], the thirteen colors that most Material widget
/// default colors are based on.
/// * [ColorScheme.brightness], which indicates if the overall [Theme]
/// is light or dark.
final Color? foregroundColor;
/// Determines the brightness of the [SystemUiOverlayStyle]: for
/// [Brightness.dark], [SystemUiOverlayStyle.light] is used and fo
/// [Brightness.light], [SystemUiOverlayStyle.dark] is used.
///
/// If this value is null then [AppBarTheme.brightness] is used
/// and if that's null then overall theme's brightness is used.
///
/// The AppBar is built within a `AnnotatedRegion<SystemUiOverlayStyle>`
/// which causes [SystemChrome.setSystemUIOverlayStyle] to be called
/// automatically. Apps should not enclose the AppBar with
/// their own [AnnotatedRegion].
///
/// See also:
///
/// * [Theme.of], which returns the current overall Material theme as
/// a [ThemeData].
/// * [ThemeData.colorScheme], the thirteen colors that most Material widget
/// default colors are based on.
/// * [ColorScheme.brightness], which indicates if the overall [Theme]
/// is light or dark.
final Brightness? brightness; final Brightness? brightness;
/// The color, opacity, and size to use for app bar icons. Typically this /// The color, opacity, and size to use for app bar icons. Typically this
...@@ -499,6 +549,7 @@ class _AppBarState extends State<AppBar> { ...@@ -499,6 +549,7 @@ class _AppBarState extends State<AppBar> {
assert(!widget.primary || debugCheckHasMediaQuery(context)); assert(!widget.primary || debugCheckHasMediaQuery(context));
assert(debugCheckHasMaterialLocalizations(context)); assert(debugCheckHasMaterialLocalizations(context));
final ThemeData theme = Theme.of(context); final ThemeData theme = Theme.of(context);
final ColorScheme colorScheme = theme.colorScheme;
final AppBarTheme appBarTheme = AppBarTheme.of(context); final AppBarTheme appBarTheme = AppBarTheme.of(context);
final ScaffoldState? scaffold = Scaffold.maybeOf(context); final ScaffoldState? scaffold = Scaffold.maybeOf(context);
final ModalRoute<dynamic>? parentRoute = ModalRoute.of(context); final ModalRoute<dynamic>? parentRoute = ModalRoute.of(context);
...@@ -510,18 +561,25 @@ class _AppBarState extends State<AppBar> { ...@@ -510,18 +561,25 @@ class _AppBarState extends State<AppBar> {
final double toolbarHeight = widget.toolbarHeight ?? kToolbarHeight; final double toolbarHeight = widget.toolbarHeight ?? kToolbarHeight;
final Color backgroundColor = widget.backgroundColor
?? appBarTheme.color
?? (colorScheme.brightness == Brightness.dark ? colorScheme.surface : colorScheme.primary);
final Color foregroundColor = widget.foregroundColor
?? appBarTheme.foregroundColor
?? (colorScheme.brightness == Brightness.dark ? colorScheme.onSurface : colorScheme.onPrimary);
IconThemeData overallIconTheme = widget.iconTheme IconThemeData overallIconTheme = widget.iconTheme
?? appBarTheme.iconTheme ?? appBarTheme.iconTheme
?? theme.primaryIconTheme; ?? theme.iconTheme.copyWith(color: foregroundColor);
IconThemeData actionsIconTheme = widget.actionsIconTheme IconThemeData actionsIconTheme = widget.actionsIconTheme
?? appBarTheme.actionsIconTheme ?? appBarTheme.actionsIconTheme
?? overallIconTheme; ?? overallIconTheme;
TextStyle? centerStyle = widget.textTheme?.headline6 TextStyle? centerStyle = widget.textTheme?.headline6
?? appBarTheme.textTheme?.headline6 ?? appBarTheme.textTheme?.headline6
?? theme.primaryTextTheme.headline6; ?? theme.primaryTextTheme.headline6?.copyWith(color: foregroundColor);
TextStyle? sideStyle = widget.textTheme?.bodyText2 TextStyle? sideStyle = widget.textTheme?.bodyText2
?? appBarTheme.textTheme?.bodyText2 ?? appBarTheme.textTheme?.bodyText2
?? theme.primaryTextTheme.bodyText2; ?? theme.primaryTextTheme.bodyText2?.copyWith(color: foregroundColor);
if (widget.toolbarOpacity != 1.0) { if (widget.toolbarOpacity != 1.0) {
final double opacity = const Interval(0.25, 1.0, curve: Curves.fastOutSlowIn).transform(widget.toolbarOpacity); final double opacity = const Interval(0.25, 1.0, curve: Curves.fastOutSlowIn).transform(widget.toolbarOpacity);
...@@ -530,10 +588,10 @@ class _AppBarState extends State<AppBar> { ...@@ -530,10 +588,10 @@ class _AppBarState extends State<AppBar> {
if (sideStyle?.color != null) if (sideStyle?.color != null)
sideStyle = sideStyle!.copyWith(color: sideStyle.color!.withOpacity(opacity)); sideStyle = sideStyle!.copyWith(color: sideStyle.color!.withOpacity(opacity));
overallIconTheme = overallIconTheme.copyWith( overallIconTheme = overallIconTheme.copyWith(
opacity: opacity * (overallIconTheme.opacity ?? 1.0) opacity: opacity * (overallIconTheme.opacity ?? 1.0),
); );
actionsIconTheme = actionsIconTheme.copyWith( actionsIconTheme = actionsIconTheme.copyWith(
opacity: opacity * (actionsIconTheme.opacity ?? 1.0) opacity: opacity * (actionsIconTheme.opacity ?? 1.0),
); );
} }
...@@ -707,21 +765,19 @@ class _AppBarState extends State<AppBar> { ...@@ -707,21 +765,19 @@ class _AppBarState extends State<AppBar> {
], ],
); );
} }
final Brightness brightness = widget.brightness final Brightness brightness = widget.brightness
?? appBarTheme.brightness ?? appBarTheme.brightness
?? theme.primaryColorBrightness; ?? colorScheme.brightness;
final SystemUiOverlayStyle overlayStyle = brightness == Brightness.dark final SystemUiOverlayStyle overlayStyle = brightness == Brightness.dark
? SystemUiOverlayStyle.light ? SystemUiOverlayStyle.light
: SystemUiOverlayStyle.dark; : SystemUiOverlayStyle.dark;
return Semantics( return Semantics(
container: true, container: true,
child: AnnotatedRegion<SystemUiOverlayStyle>( child: AnnotatedRegion<SystemUiOverlayStyle>(
value: overlayStyle, value: overlayStyle,
child: Material( child: Material(
color: widget.backgroundColor color: backgroundColor,
?? appBarTheme.color
?? theme.primaryColor,
elevation: widget.elevation elevation: widget.elevation
?? appBarTheme.elevation ?? appBarTheme.elevation
?? _defaultElevation, ?? _defaultElevation,
......
...@@ -33,6 +33,7 @@ class AppBarTheme with Diagnosticable { ...@@ -33,6 +33,7 @@ class AppBarTheme with Diagnosticable {
const AppBarTheme({ const AppBarTheme({
this.brightness, this.brightness,
this.color, this.color,
this.foregroundColor,
this.elevation, this.elevation,
this.shadowColor, this.shadowColor,
this.iconTheme, this.iconTheme,
...@@ -42,16 +43,66 @@ class AppBarTheme with Diagnosticable { ...@@ -42,16 +43,66 @@ class AppBarTheme with Diagnosticable {
this.titleSpacing, this.titleSpacing,
}); });
/// Default value for [AppBar.brightness]. /// AppBar uses this value to determine the default (background) [color] and
/// [foregroundColor] as well as the app bar's [SystemUiOverlayStyle].
/// ///
/// If null, [AppBar] uses [ThemeData.primaryColorBrightness]. /// For [Brightness.dark], [SystemUiOverlayStyle.light] is used and for
/// [Brightness.light], [SystemUiOverlayStyle.dark] is used.
///
/// See also:
///
/// * [AppBar.brightness], which overrides the this value and the overall
/// theme's [ColorScheme.brightness].
/// * [Theme.of], which returns the current overall Material theme as
/// a [ThemeData].
/// * [ThemeData.colorScheme], the thirteen colors that most Material widget
/// default colors are based on.
/// * [ColorScheme.brightness], which indicates if the overall [Theme]
/// is light or dark.
final Brightness? brightness; final Brightness? brightness;
/// Default value for [AppBar.backgroundColor]. /// The app bar's background color.
///
/// If null, [AppBar] uses the overall theme's [ColorScheme.primary] if the
/// overall theme's brightness is [Brightness.light], and [ColorScheme.surface]
/// if the overall theme's [brightness] is [Brightness.dark].
/// ///
/// If null, [AppBar] uses [ThemeData.primaryColor]. /// See also:
///
/// * [AppBar.backgroundColor], which specifies the AppBar's background color
/// and overrides the background color defined by this theme.
/// * [foregroundColor], which specifies the color for icons and text within
/// the app bar.
/// * [Theme.of], which returns the current overall Material theme as
/// a [ThemeData].
/// * [ThemeData.colorScheme], the thirteen colors that most Material widget
/// default colors are based on.
/// * [ColorScheme.brightness], which indicates if the overall [Theme]
/// is light or dark.
final Color? color; final Color? color;
/// The default color for [Text] and [Icon]s within the app bar.
///
/// If null, [AppBar] uses the overall theme's [ColorScheme.onPrimary] if the
/// overall theme's brightness is [Brightness.light], and [ColorScheme.onSurface]
/// if the overall theme's [brightness] is [Brightness.dark].
///
/// This color is used to configure [DefaultTextStyle] and [IconTheme]
/// widgets.
///
/// See also:
///
/// * [AppBar.foregroundColor], which specifies the app bar's text and icon
/// colors and overrides the foreground color defined by this theme.
/// * [color], which specifies the app bar's background color.
/// * [Theme.of], which returns the current overall Material theme as
/// a [ThemeData].
/// * [ThemeData.colorScheme], the thirteen colors that most Material widget
/// default colors are based on.
/// * [ColorScheme.brightness], which indicates if the overall [Theme]
/// is light or dark.
final Color? foregroundColor;
/// Default value for [AppBar.elevation]. /// Default value for [AppBar.elevation].
/// ///
/// If null, [AppBar] uses a default value of 4.0. /// If null, [AppBar] uses a default value of 4.0.
...@@ -93,6 +144,7 @@ class AppBarTheme with Diagnosticable { ...@@ -93,6 +144,7 @@ class AppBarTheme with Diagnosticable {
IconThemeData? actionsIconTheme, IconThemeData? actionsIconTheme,
Brightness? brightness, Brightness? brightness,
Color? color, Color? color,
Color? foregroundColor,
double? elevation, double? elevation,
Color? shadowColor, Color? shadowColor,
IconThemeData? iconTheme, IconThemeData? iconTheme,
...@@ -103,6 +155,7 @@ class AppBarTheme with Diagnosticable { ...@@ -103,6 +155,7 @@ class AppBarTheme with Diagnosticable {
return AppBarTheme( return AppBarTheme(
brightness: brightness ?? this.brightness, brightness: brightness ?? this.brightness,
color: color ?? this.color, color: color ?? this.color,
foregroundColor: foregroundColor ?? this.foregroundColor,
elevation: elevation ?? this.elevation, elevation: elevation ?? this.elevation,
shadowColor: shadowColor ?? this.shadowColor, shadowColor: shadowColor ?? this.shadowColor,
iconTheme: iconTheme ?? this.iconTheme, iconTheme: iconTheme ?? this.iconTheme,
...@@ -128,6 +181,7 @@ class AppBarTheme with Diagnosticable { ...@@ -128,6 +181,7 @@ class AppBarTheme with Diagnosticable {
return AppBarTheme( return AppBarTheme(
brightness: t < 0.5 ? a?.brightness : b?.brightness, brightness: t < 0.5 ? a?.brightness : b?.brightness,
color: Color.lerp(a?.color, b?.color, t), color: Color.lerp(a?.color, b?.color, t),
foregroundColor: Color.lerp(a?.foregroundColor, b?.foregroundColor, t),
elevation: lerpDouble(a?.elevation, b?.elevation, t), elevation: lerpDouble(a?.elevation, b?.elevation, t),
shadowColor: Color.lerp(a?.shadowColor, b?.shadowColor, t), shadowColor: Color.lerp(a?.shadowColor, b?.shadowColor, t),
iconTheme: IconThemeData.lerp(a?.iconTheme, b?.iconTheme, t), iconTheme: IconThemeData.lerp(a?.iconTheme, b?.iconTheme, t),
...@@ -143,6 +197,7 @@ class AppBarTheme with Diagnosticable { ...@@ -143,6 +197,7 @@ class AppBarTheme with Diagnosticable {
return hashValues( return hashValues(
brightness, brightness,
color, color,
foregroundColor,
elevation, elevation,
shadowColor, shadowColor,
iconTheme, iconTheme,
...@@ -162,6 +217,7 @@ class AppBarTheme with Diagnosticable { ...@@ -162,6 +217,7 @@ class AppBarTheme with Diagnosticable {
return other is AppBarTheme return other is AppBarTheme
&& other.brightness == brightness && other.brightness == brightness
&& other.color == color && other.color == color
&& other.foregroundColor == foregroundColor
&& other.elevation == elevation && other.elevation == elevation
&& other.shadowColor == shadowColor && other.shadowColor == shadowColor
&& other.iconTheme == iconTheme && other.iconTheme == iconTheme
...@@ -176,6 +232,7 @@ class AppBarTheme with Diagnosticable { ...@@ -176,6 +232,7 @@ class AppBarTheme with Diagnosticable {
super.debugFillProperties(properties); super.debugFillProperties(properties);
properties.add(DiagnosticsProperty<Brightness>('brightness', brightness, defaultValue: null)); properties.add(DiagnosticsProperty<Brightness>('brightness', brightness, defaultValue: null));
properties.add(ColorProperty('color', color, defaultValue: null)); properties.add(ColorProperty('color', color, defaultValue: null));
properties.add(ColorProperty('foregroundColor', foregroundColor, defaultValue: null));
properties.add(DiagnosticsProperty<double>('elevation', elevation, defaultValue: null)); properties.add(DiagnosticsProperty<double>('elevation', elevation, defaultValue: null));
properties.add(ColorProperty('shadowColor', shadowColor, defaultValue: null)); properties.add(ColorProperty('shadowColor', shadowColor, defaultValue: null));
properties.add(DiagnosticsProperty<IconThemeData>('iconTheme', iconTheme, defaultValue: null)); properties.add(DiagnosticsProperty<IconThemeData>('iconTheme', iconTheme, defaultValue: null));
......
...@@ -1769,6 +1769,7 @@ void main() { ...@@ -1769,6 +1769,7 @@ void main() {
)); ));
expect(darkTheme.primaryColorBrightness, Brightness.dark); expect(darkTheme.primaryColorBrightness, Brightness.dark);
expect(darkTheme.colorScheme.brightness, Brightness.dark);
expect(SystemChrome.latestStyle, const SystemUiOverlayStyle( expect(SystemChrome.latestStyle, const SystemUiOverlayStyle(
statusBarBrightness: Brightness.dark, statusBarBrightness: Brightness.dark,
statusBarIconBrightness: Brightness.light, statusBarIconBrightness: Brightness.light,
...@@ -1777,14 +1778,17 @@ void main() { ...@@ -1777,14 +1778,17 @@ void main() {
testWidgets('AppBar draws a dark system bar for a light background', (WidgetTester tester) async { testWidgets('AppBar draws a dark system bar for a light background', (WidgetTester tester) async {
final ThemeData lightTheme = ThemeData(primaryColor: Colors.white); final ThemeData lightTheme = ThemeData(primaryColor: Colors.white);
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(
theme: lightTheme, MaterialApp(
home: Scaffold( theme: lightTheme,
appBar: AppBar(title: const Text('test')), home: Scaffold(
appBar: AppBar(title: const Text('test')),
),
), ),
)); );
expect(lightTheme.primaryColorBrightness, Brightness.light); expect(lightTheme.primaryColorBrightness, Brightness.light);
expect(lightTheme.colorScheme.brightness, Brightness.light);
expect(SystemChrome.latestStyle, const SystemUiOverlayStyle( expect(SystemChrome.latestStyle, const SystemUiOverlayStyle(
statusBarBrightness: Brightness.light, statusBarBrightness: Brightness.light,
statusBarIconBrightness: Brightness.dark, statusBarIconBrightness: Brightness.dark,
......
...@@ -29,7 +29,7 @@ void main() { ...@@ -29,7 +29,7 @@ void main() {
final RichText actionIconText = _getAppBarIconRichText(tester); final RichText actionIconText = _getAppBarIconRichText(tester);
final DefaultTextStyle text = _getAppBarText(tester); final DefaultTextStyle text = _getAppBarText(tester);
expect(SystemChrome.latestStyle!.statusBarBrightness, Brightness.dark); expect(SystemChrome.latestStyle!.statusBarBrightness, SystemUiOverlayStyle.dark.statusBarBrightness);
expect(widget.color, Colors.blue); expect(widget.color, Colors.blue);
expect(widget.elevation, 4.0); expect(widget.elevation, 4.0);
expect(widget.shadowColor, Colors.black); expect(widget.shadowColor, Colors.black);
...@@ -77,23 +77,25 @@ void main() { ...@@ -77,23 +77,25 @@ void main() {
const IconThemeData actionsIconThemeData = IconThemeData(color: Colors.lightBlue); const IconThemeData actionsIconThemeData = IconThemeData(color: Colors.lightBlue);
const TextTheme textTheme = TextTheme(headline6: TextStyle(color: Colors.orange), bodyText2: TextStyle(color: Colors.pink)); const TextTheme textTheme = TextTheme(headline6: TextStyle(color: Colors.orange), bodyText2: TextStyle(color: Colors.pink));
final ThemeData themeData = _themeData().copyWith(appBarTheme: _appBarTheme()); await tester.pumpWidget(
MaterialApp(
await tester.pumpWidget(MaterialApp( theme: ThemeData.from(colorScheme: const ColorScheme.light()),
theme: themeData, home: Scaffold(
home: Scaffold(appBar: AppBar( appBar: AppBar(
backgroundColor: color, backgroundColor: color,
brightness: brightness, brightness: brightness,
elevation: elevation, elevation: elevation,
shadowColor: shadowColor, shadowColor: shadowColor,
iconTheme: iconThemeData, iconTheme: iconThemeData,
actionsIconTheme: actionsIconThemeData, actionsIconTheme: actionsIconThemeData,
textTheme: textTheme, textTheme: textTheme,
actions: <Widget>[ actions: <Widget>[
IconButton(icon: const Icon(Icons.share), onPressed: () { }), IconButton(icon: const Icon(Icons.share), onPressed: () { }),
], ],
)), ),
)); ),
),
);
final Material widget = _getAppBarMaterial(tester); final Material widget = _getAppBarMaterial(tester);
final IconTheme iconTheme = _getAppBarIconTheme(tester); final IconTheme iconTheme = _getAppBarIconTheme(tester);
...@@ -116,10 +118,8 @@ void main() { ...@@ -116,10 +118,8 @@ void main() {
const IconThemeData iconThemeData = IconThemeData(color: Colors.green); const IconThemeData iconThemeData = IconThemeData(color: Colors.green);
const IconThemeData actionsIconThemeData = IconThemeData(color: Colors.lightBlue); const IconThemeData actionsIconThemeData = IconThemeData(color: Colors.lightBlue);
final ThemeData themeData = _themeData().copyWith(appBarTheme: _appBarTheme());
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(MaterialApp(
theme: themeData, theme: ThemeData.from(colorScheme: const ColorScheme.light()),
home: Scaffold(appBar: AppBar( home: Scaffold(appBar: AppBar(
iconTheme: iconThemeData, iconTheme: iconThemeData,
actionsIconTheme: actionsIconThemeData, actionsIconTheme: actionsIconThemeData,
...@@ -135,16 +135,20 @@ void main() { ...@@ -135,16 +135,20 @@ void main() {
testWidgets('AppBarTheme properties take priority over ThemeData properties', (WidgetTester tester) async { testWidgets('AppBarTheme properties take priority over ThemeData properties', (WidgetTester tester) async {
final AppBarTheme appBarTheme = _appBarTheme(); final AppBarTheme appBarTheme = _appBarTheme();
final ThemeData themeData = _themeData().copyWith(appBarTheme: _appBarTheme());
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(
theme: themeData, MaterialApp(
home: Scaffold(appBar: AppBar( theme: ThemeData.from(colorScheme: const ColorScheme.light())
actions: <Widget>[ .copyWith(appBarTheme: _appBarTheme()),
IconButton(icon: const Icon(Icons.share), onPressed: () { }), home: Scaffold(
], appBar: AppBar(
)), actions: <Widget>[
)); IconButton(icon: const Icon(Icons.share), onPressed: () { }),
],
),
),
),
);
final Material widget = _getAppBarMaterial(tester); final Material widget = _getAppBarMaterial(tester);
final IconTheme iconTheme = _getAppBarIconTheme(tester); final IconTheme iconTheme = _getAppBarIconTheme(tester);
...@@ -162,33 +166,80 @@ void main() { ...@@ -162,33 +166,80 @@ void main() {
expect(text.style, appBarTheme.textTheme!.bodyText2); expect(text.style, appBarTheme.textTheme!.bodyText2);
}); });
testWidgets('ThemeData properties are used when no AppBarTheme is set', (WidgetTester tester) async { testWidgets('ThemeData colorScheme is used when no AppBarTheme is set', (WidgetTester tester) async {
final ThemeData themeData = _themeData(); late ThemeData theme;
Widget buildFrame(ThemeData appTheme) {
await tester.pumpWidget(MaterialApp( return MaterialApp(
theme: themeData, theme: appTheme,
home: Scaffold(appBar: AppBar( home: Builder(
actions: <Widget>[ builder: (BuildContext context) {
IconButton(icon: const Icon(Icons.share), onPressed: () { }), // This ThemeData has been localized with ThemeData.localize. The
], // appTheme parameter has not, so its textTheme is incomplete.
)), theme = Theme.of(context);
)); return Scaffold(
appBar: AppBar(
final Material widget = _getAppBarMaterial(tester); actions: <Widget>[
final IconTheme iconTheme = _getAppBarIconTheme(tester); IconButton(icon: const Icon(Icons.share), onPressed: () { }),
final IconTheme actionsIconTheme = _getAppBarActionsIconTheme(tester); ],
final RichText actionIconText = _getAppBarIconRichText(tester); ),
final DefaultTextStyle text = _getAppBarText(tester); );
},
expect(SystemChrome.latestStyle!.statusBarBrightness, themeData.brightness); ),
expect(widget.color, themeData.primaryColor); );
expect(widget.elevation, 4.0); }
expect(widget.shadowColor, Colors.black);
expect(iconTheme.data, themeData.primaryIconTheme); // AppBar defaults for light themes:
expect(actionsIconTheme.data, themeData.primaryIconTheme); // - elevation: 4
expect(actionIconText.text.style!.color, themeData.primaryIconTheme.color); // - shadow color: black
// Default value for ThemeData.typography is Typography.material2014() // - background color: ColorScheme.primary
expect(text.style, Typography.material2014().englishLike.bodyText2!.merge(Typography.material2014().white.bodyText2).merge(themeData.primaryTextTheme.bodyText2)); // - foreground color: ColorScheme.onPrimary
// - actions text: style bodyText2, foreground color
// - status bar brightness: dark (based on color scheme brightness)
{
await tester.pumpWidget(buildFrame(ThemeData.from(colorScheme: const ColorScheme.light())));
final Material widget = _getAppBarMaterial(tester);
final IconTheme iconTheme = _getAppBarIconTheme(tester);
final IconTheme actionsIconTheme = _getAppBarActionsIconTheme(tester);
final RichText actionIconText = _getAppBarIconRichText(tester);
final DefaultTextStyle text = _getAppBarText(tester);
expect(SystemChrome.latestStyle!.statusBarBrightness, SystemUiOverlayStyle.dark.statusBarBrightness);
expect(widget.color, theme.colorScheme.primary);
expect(widget.elevation, 4.0);
expect(widget.shadowColor, Colors.black);
expect(iconTheme.data.color, theme.colorScheme.onPrimary);
expect(actionsIconTheme.data.color, theme.colorScheme.onPrimary);
expect(actionIconText.text.style!.color, theme.colorScheme.onPrimary);
expect(text.style.compareTo(theme.textTheme.bodyText2!.copyWith(color: theme.colorScheme.onPrimary)), RenderComparison.identical);
}
// AppBar defaults for dark themes:
// - elevation: 4
// - shadow color: black
// - background color: ColorScheme.surface
// - foreground color: ColorScheme.onSurface
// - actions text: style bodyText2, foreground color
// - status bar brightness: dark (based on background color)
{
await tester.pumpWidget(buildFrame(ThemeData.from(colorScheme: const ColorScheme.dark())));
await tester.pumpAndSettle(); // Theme change animation
final Material widget = _getAppBarMaterial(tester);
final IconTheme iconTheme = _getAppBarIconTheme(tester);
final IconTheme actionsIconTheme = _getAppBarActionsIconTheme(tester);
final RichText actionIconText = _getAppBarIconRichText(tester);
final DefaultTextStyle text = _getAppBarText(tester);
expect(SystemChrome.latestStyle!.statusBarBrightness, SystemUiOverlayStyle.light.statusBarBrightness);
expect(widget.color, theme.colorScheme.surface);
expect(widget.elevation, 4.0);
expect(widget.shadowColor, Colors.black);
expect(iconTheme.data.color, theme.colorScheme.onSurface);
expect(actionsIconTheme.data.color, theme.colorScheme.onSurface);
expect(actionIconText.text.style!.color, theme.colorScheme.onSurface);
expect(text.style.compareTo(theme.textTheme.bodyText2!.copyWith(color: theme.colorScheme.onSurface)), RenderComparison.identical);
}
}); });
testWidgets('AppBar uses AppBarTheme.centerTitle when centerTitle is null', (WidgetTester tester) async { testWidgets('AppBar uses AppBarTheme.centerTitle when centerTitle is null', (WidgetTester tester) async {
...@@ -375,15 +426,6 @@ AppBarTheme _appBarTheme() { ...@@ -375,15 +426,6 @@ AppBarTheme _appBarTheme() {
); );
} }
ThemeData _themeData() {
return ThemeData(
primaryColor: Colors.purple,
brightness: Brightness.dark,
primaryIconTheme: const IconThemeData(color: Colors.green),
primaryTextTheme: const TextTheme(headline6: TextStyle(color: Colors.orange), bodyText2: TextStyle(color: Colors.pink)),
);
}
Material _getAppBarMaterial(WidgetTester tester) { Material _getAppBarMaterial(WidgetTester tester) {
return tester.widget<Material>( return tester.widget<Material>(
find.descendant( find.descendant(
......
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