Revert "AppBar draws its defaults from theme.colorScheme (#69251)" (#70212)
diff --git a/packages/flutter/lib/src/material/app_bar.dart b/packages/flutter/lib/src/material/app_bar.dart
index 46cb581..78ac136 100644
--- a/packages/flutter/lib/src/material/app_bar.dart
+++ b/packages/flutter/lib/src/material/app_bar.dart
@@ -11,7 +11,6 @@
import 'app_bar_theme.dart';
import 'back_button.dart';
-import 'color_scheme.dart';
import 'constants.dart';
import 'debug.dart';
import 'flexible_space_bar.dart';
@@ -197,7 +196,6 @@
this.shadowColor,
this.shape,
this.backgroundColor,
- this.foregroundColor,
this.brightness,
this.iconTheme,
this.actionsIconTheme,
@@ -359,68 +357,20 @@
/// zero.
final ShapeBorder? shape;
- /// The fill color to use for the app bar's [Material].
+ /// The color to use for the app bar's material. Typically this should be set
+ /// along with [brightness], [iconTheme], [textTheme].
///
- /// If null, then the [AppBarTheme.color] is used. If that value is also
- /// null, then [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].
- ///
- /// 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.
+ /// If this property is null, then [AppBarTheme.color] of
+ /// [ThemeData.appBarTheme] is used. If that is also null, then
+ /// [ThemeData.primaryColor] is used.
final Color? backgroundColor;
- /// The default color for [Text] and [Icon]s within the app bar.
+ /// The brightness of the app bar's material. Typically this is set along
+ /// with [backgroundColor], [iconTheme], [textTheme].
///
- /// If null, then [AppBarTheme.foregroundColor] is used. If that
- /// value is also null, then [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] 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.
+ /// If this property is null, then [AppBarTheme.brightness] of
+ /// [ThemeData.appBarTheme] is used. If that is also null, then
+ /// [ThemeData.primaryColorBrightness] is used.
final Brightness? brightness;
/// The color, opacity, and size to use for app bar icons. Typically this
@@ -549,7 +499,6 @@
assert(!widget.primary || debugCheckHasMediaQuery(context));
assert(debugCheckHasMaterialLocalizations(context));
final ThemeData theme = Theme.of(context);
- final ColorScheme colorScheme = theme.colorScheme;
final AppBarTheme appBarTheme = AppBarTheme.of(context);
final ScaffoldState? scaffold = Scaffold.maybeOf(context);
final ModalRoute<dynamic>? parentRoute = ModalRoute.of(context);
@@ -561,25 +510,18 @@
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
?? appBarTheme.iconTheme
- ?? theme.iconTheme.copyWith(color: foregroundColor);
+ ?? theme.primaryIconTheme;
IconThemeData actionsIconTheme = widget.actionsIconTheme
?? appBarTheme.actionsIconTheme
?? overallIconTheme;
TextStyle? centerStyle = widget.textTheme?.headline6
?? appBarTheme.textTheme?.headline6
- ?? theme.primaryTextTheme.headline6?.copyWith(color: foregroundColor);
+ ?? theme.primaryTextTheme.headline6;
TextStyle? sideStyle = widget.textTheme?.bodyText2
?? appBarTheme.textTheme?.bodyText2
- ?? theme.primaryTextTheme.bodyText2?.copyWith(color: foregroundColor);
+ ?? theme.primaryTextTheme.bodyText2;
if (widget.toolbarOpacity != 1.0) {
final double opacity = const Interval(0.25, 1.0, curve: Curves.fastOutSlowIn).transform(widget.toolbarOpacity);
@@ -588,10 +530,10 @@
if (sideStyle?.color != null)
sideStyle = sideStyle!.copyWith(color: sideStyle.color!.withOpacity(opacity));
overallIconTheme = overallIconTheme.copyWith(
- opacity: opacity * (overallIconTheme.opacity ?? 1.0),
+ opacity: opacity * (overallIconTheme.opacity ?? 1.0)
);
actionsIconTheme = actionsIconTheme.copyWith(
- opacity: opacity * (actionsIconTheme.opacity ?? 1.0),
+ opacity: opacity * (actionsIconTheme.opacity ?? 1.0)
);
}
@@ -765,19 +707,21 @@
],
);
}
-
final Brightness brightness = widget.brightness
?? appBarTheme.brightness
- ?? colorScheme.brightness;
+ ?? theme.primaryColorBrightness;
final SystemUiOverlayStyle overlayStyle = brightness == Brightness.dark
? SystemUiOverlayStyle.light
: SystemUiOverlayStyle.dark;
+
return Semantics(
container: true,
child: AnnotatedRegion<SystemUiOverlayStyle>(
value: overlayStyle,
child: Material(
- color: backgroundColor,
+ color: widget.backgroundColor
+ ?? appBarTheme.color
+ ?? theme.primaryColor,
elevation: widget.elevation
?? appBarTheme.elevation
?? _defaultElevation,
diff --git a/packages/flutter/lib/src/material/app_bar_theme.dart b/packages/flutter/lib/src/material/app_bar_theme.dart
index 3ce1708..c6d0a5c 100644
--- a/packages/flutter/lib/src/material/app_bar_theme.dart
+++ b/packages/flutter/lib/src/material/app_bar_theme.dart
@@ -33,7 +33,6 @@
const AppBarTheme({
this.brightness,
this.color,
- this.foregroundColor,
this.elevation,
this.shadowColor,
this.iconTheme,
@@ -43,66 +42,16 @@
this.titleSpacing,
});
- /// AppBar uses this value to determine the default (background) [color] and
- /// [foregroundColor] as well as the app bar's [SystemUiOverlayStyle].
+ /// Default value for [AppBar.brightness].
///
- /// 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.
+ /// If null, [AppBar] uses [ThemeData.primaryColorBrightness].
final Brightness? brightness;
- /// The app bar's background color.
+ /// Default value for [AppBar.backgroundColor].
///
- /// 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].
- ///
- /// 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.
+ /// If null, [AppBar] uses [ThemeData.primaryColor].
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].
///
/// If null, [AppBar] uses a default value of 4.0.
@@ -144,7 +93,6 @@
IconThemeData? actionsIconTheme,
Brightness? brightness,
Color? color,
- Color? foregroundColor,
double? elevation,
Color? shadowColor,
IconThemeData? iconTheme,
@@ -155,7 +103,6 @@
return AppBarTheme(
brightness: brightness ?? this.brightness,
color: color ?? this.color,
- foregroundColor: foregroundColor ?? this.foregroundColor,
elevation: elevation ?? this.elevation,
shadowColor: shadowColor ?? this.shadowColor,
iconTheme: iconTheme ?? this.iconTheme,
@@ -181,7 +128,6 @@
return AppBarTheme(
brightness: t < 0.5 ? a?.brightness : b?.brightness,
color: Color.lerp(a?.color, b?.color, t),
- foregroundColor: Color.lerp(a?.foregroundColor, b?.foregroundColor, t),
elevation: lerpDouble(a?.elevation, b?.elevation, t),
shadowColor: Color.lerp(a?.shadowColor, b?.shadowColor, t),
iconTheme: IconThemeData.lerp(a?.iconTheme, b?.iconTheme, t),
@@ -197,7 +143,6 @@
return hashValues(
brightness,
color,
- foregroundColor,
elevation,
shadowColor,
iconTheme,
@@ -217,7 +162,6 @@
return other is AppBarTheme
&& other.brightness == brightness
&& other.color == color
- && other.foregroundColor == foregroundColor
&& other.elevation == elevation
&& other.shadowColor == shadowColor
&& other.iconTheme == iconTheme
@@ -232,7 +176,6 @@
super.debugFillProperties(properties);
properties.add(DiagnosticsProperty<Brightness>('brightness', brightness, 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(ColorProperty('shadowColor', shadowColor, defaultValue: null));
properties.add(DiagnosticsProperty<IconThemeData>('iconTheme', iconTheme, defaultValue: null));
diff --git a/packages/flutter/test/material/app_bar_test.dart b/packages/flutter/test/material/app_bar_test.dart
index 49a0d4c..5af0cf6 100644
--- a/packages/flutter/test/material/app_bar_test.dart
+++ b/packages/flutter/test/material/app_bar_test.dart
@@ -1769,7 +1769,6 @@
));
expect(darkTheme.primaryColorBrightness, Brightness.dark);
- expect(darkTheme.colorScheme.brightness, Brightness.dark);
expect(SystemChrome.latestStyle, const SystemUiOverlayStyle(
statusBarBrightness: Brightness.dark,
statusBarIconBrightness: Brightness.light,
@@ -1778,17 +1777,14 @@
testWidgets('AppBar draws a dark system bar for a light background', (WidgetTester tester) async {
final ThemeData lightTheme = ThemeData(primaryColor: Colors.white);
- await tester.pumpWidget(
- MaterialApp(
- theme: lightTheme,
- home: Scaffold(
- appBar: AppBar(title: const Text('test')),
- ),
+ await tester.pumpWidget(MaterialApp(
+ theme: lightTheme,
+ home: Scaffold(
+ appBar: AppBar(title: const Text('test')),
),
- );
+ ));
expect(lightTheme.primaryColorBrightness, Brightness.light);
- expect(lightTheme.colorScheme.brightness, Brightness.light);
expect(SystemChrome.latestStyle, const SystemUiOverlayStyle(
statusBarBrightness: Brightness.light,
statusBarIconBrightness: Brightness.dark,
diff --git a/packages/flutter/test/material/app_bar_theme_test.dart b/packages/flutter/test/material/app_bar_theme_test.dart
index e37ea3c..3a83eba 100644
--- a/packages/flutter/test/material/app_bar_theme_test.dart
+++ b/packages/flutter/test/material/app_bar_theme_test.dart
@@ -29,7 +29,7 @@
final RichText actionIconText = _getAppBarIconRichText(tester);
final DefaultTextStyle text = _getAppBarText(tester);
- expect(SystemChrome.latestStyle!.statusBarBrightness, SystemUiOverlayStyle.dark.statusBarBrightness);
+ expect(SystemChrome.latestStyle!.statusBarBrightness, Brightness.dark);
expect(widget.color, Colors.blue);
expect(widget.elevation, 4.0);
expect(widget.shadowColor, Colors.black);
@@ -77,25 +77,23 @@
const IconThemeData actionsIconThemeData = IconThemeData(color: Colors.lightBlue);
const TextTheme textTheme = TextTheme(headline6: TextStyle(color: Colors.orange), bodyText2: TextStyle(color: Colors.pink));
- await tester.pumpWidget(
- MaterialApp(
- theme: ThemeData.from(colorScheme: const ColorScheme.light()),
- home: Scaffold(
- appBar: AppBar(
- backgroundColor: color,
- brightness: brightness,
- elevation: elevation,
- shadowColor: shadowColor,
- iconTheme: iconThemeData,
- actionsIconTheme: actionsIconThemeData,
- textTheme: textTheme,
- actions: <Widget>[
- IconButton(icon: const Icon(Icons.share), onPressed: () { }),
- ],
- ),
- ),
- ),
- );
+ final ThemeData themeData = _themeData().copyWith(appBarTheme: _appBarTheme());
+
+ await tester.pumpWidget(MaterialApp(
+ theme: themeData,
+ home: Scaffold(appBar: AppBar(
+ backgroundColor: color,
+ brightness: brightness,
+ elevation: elevation,
+ shadowColor: shadowColor,
+ iconTheme: iconThemeData,
+ actionsIconTheme: actionsIconThemeData,
+ textTheme: textTheme,
+ actions: <Widget>[
+ IconButton(icon: const Icon(Icons.share), onPressed: () { }),
+ ],
+ )),
+ ));
final Material widget = _getAppBarMaterial(tester);
final IconTheme iconTheme = _getAppBarIconTheme(tester);
@@ -118,8 +116,10 @@
const IconThemeData iconThemeData = IconThemeData(color: Colors.green);
const IconThemeData actionsIconThemeData = IconThemeData(color: Colors.lightBlue);
+ final ThemeData themeData = _themeData().copyWith(appBarTheme: _appBarTheme());
+
await tester.pumpWidget(MaterialApp(
- theme: ThemeData.from(colorScheme: const ColorScheme.light()),
+ theme: themeData,
home: Scaffold(appBar: AppBar(
iconTheme: iconThemeData,
actionsIconTheme: actionsIconThemeData,
@@ -135,20 +135,16 @@
testWidgets('AppBarTheme properties take priority over ThemeData properties', (WidgetTester tester) async {
final AppBarTheme appBarTheme = _appBarTheme();
+ final ThemeData themeData = _themeData().copyWith(appBarTheme: _appBarTheme());
- await tester.pumpWidget(
- MaterialApp(
- theme: ThemeData.from(colorScheme: const ColorScheme.light())
- .copyWith(appBarTheme: _appBarTheme()),
- home: Scaffold(
- appBar: AppBar(
- actions: <Widget>[
- IconButton(icon: const Icon(Icons.share), onPressed: () { }),
- ],
- ),
- ),
- ),
- );
+ await tester.pumpWidget(MaterialApp(
+ theme: themeData,
+ home: Scaffold(appBar: AppBar(
+ actions: <Widget>[
+ IconButton(icon: const Icon(Icons.share), onPressed: () { }),
+ ],
+ )),
+ ));
final Material widget = _getAppBarMaterial(tester);
final IconTheme iconTheme = _getAppBarIconTheme(tester);
@@ -166,80 +162,33 @@
expect(text.style, appBarTheme.textTheme!.bodyText2);
});
- testWidgets('ThemeData colorScheme is used when no AppBarTheme is set', (WidgetTester tester) async {
- late ThemeData theme;
- Widget buildFrame(ThemeData appTheme) {
- return MaterialApp(
- theme: appTheme,
- home: Builder(
- builder: (BuildContext context) {
- // 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(
- actions: <Widget>[
- IconButton(icon: const Icon(Icons.share), onPressed: () { }),
- ],
- ),
- );
- },
- ),
- );
- }
+ testWidgets('ThemeData properties are used when no AppBarTheme is set', (WidgetTester tester) async {
+ final ThemeData themeData = _themeData();
- // AppBar defaults for light themes:
- // - elevation: 4
- // - shadow color: black
- // - background color: ColorScheme.primary
- // - 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())));
+ await tester.pumpWidget(MaterialApp(
+ theme: themeData,
+ home: Scaffold(appBar: AppBar(
+ actions: <Widget>[
+ IconButton(icon: const Icon(Icons.share), onPressed: () { }),
+ ],
+ )),
+ ));
- 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);
+ 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);
- }
+ 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);
+ expect(actionsIconTheme.data, themeData.primaryIconTheme);
+ expect(actionIconText.text.style!.color, themeData.primaryIconTheme.color);
+ // Default value for ThemeData.typography is Typography.material2014()
+ expect(text.style, Typography.material2014().englishLike.bodyText2!.merge(Typography.material2014().white.bodyText2).merge(themeData.primaryTextTheme.bodyText2));
});
testWidgets('AppBar uses AppBarTheme.centerTitle when centerTitle is null', (WidgetTester tester) async {
@@ -426,6 +375,15 @@
);
}
+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) {
return tester.widget<Material>(
find.descendant(