diff --git a/packages/flutter/lib/src/material/app_bar.dart b/packages/flutter/lib/src/material/app_bar.dart index 15089fbe82..c7c443f12d 100644 --- a/packages/flutter/lib/src/material/app_bar.dart +++ b/packages/flutter/lib/src/material/app_bar.dart @@ -192,7 +192,7 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget { this.bottomOpacity = 1.0, this.toolbarHeight, this.leadingWidth, - this.backwardsCompatibility = true, + this.backwardsCompatibility, this.toolbarTextStyle, this.titleTextStyle, this.systemOverlayStyle, @@ -201,7 +201,6 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget { assert(primary != null), assert(toolbarOpacity != null), assert(bottomOpacity != null), - assert(backwardsCompatibility != null), preferredSize = Size.fromHeight(toolbarHeight ?? kToolbarHeight + (bottom?.preferredSize.height ?? 0.0)), super(key: key); @@ -609,16 +608,18 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget { /// [iconTheme], [actionsIconTheme] properties, and the original use of /// the [textTheme] and [brightness] properties. /// - /// This property is true by default. + /// If this property is null, then [AppBarTheme.backwardsCompatibility] of + /// [ThemeData.appBarTheme] is used. If that is also null, the default + /// value is true. /// /// This is a temporary property. When setting it to false is no - /// longer considereed a breaking change, it will be depreacted and + /// longer considered a breaking change, it will be depreacted and /// its default value will be changed to false. App developers are /// encouraged to opt into the new features by setting it to false /// and using the [foregroundColor] and [systemOverlayStyle] /// properties as needed. /// {@endtemplate} - final bool backwardsCompatibility; + final bool? backwardsCompatibility; /// {@template flutter.material.appbar.toolbarTextStyle} /// The default text style for the AppBar's [leading], and @@ -724,8 +725,9 @@ class _AppBarState extends State { final bool useCloseButton = parentRoute is PageRoute && parentRoute.fullscreenDialog; final double toolbarHeight = widget.toolbarHeight ?? kToolbarHeight; + final bool backwardsCompatibility = widget.backwardsCompatibility ?? appBarTheme.backwardsCompatibility ?? true; - final Color backgroundColor = widget.backwardsCompatibility + final Color backgroundColor = backwardsCompatibility ? widget.backgroundColor ?? appBarTheme.color ?? theme.primaryColor @@ -737,7 +739,7 @@ class _AppBarState extends State { ?? appBarTheme.foregroundColor ?? (colorScheme.brightness == Brightness.dark ? colorScheme.onSurface : colorScheme.onPrimary); - IconThemeData overallIconTheme = widget.backwardsCompatibility + IconThemeData overallIconTheme = backwardsCompatibility ? widget.iconTheme ?? appBarTheme.iconTheme ?? theme.primaryIconTheme @@ -749,7 +751,7 @@ class _AppBarState extends State { ?? appBarTheme.actionsIconTheme ?? overallIconTheme; - TextStyle? toolbarTextStyle = widget.backwardsCompatibility + TextStyle? toolbarTextStyle = backwardsCompatibility ? widget.textTheme?.bodyText2 ?? appBarTheme.textTheme?.bodyText2 ?? theme.primaryTextTheme.bodyText2 @@ -757,7 +759,7 @@ class _AppBarState extends State { ?? appBarTheme.toolbarTextStyle ?? theme.textTheme.bodyText2?.copyWith(color: foregroundColor); - TextStyle? titleTextStyle = widget.backwardsCompatibility + TextStyle? titleTextStyle = backwardsCompatibility ? widget.textTheme?.headline6 ?? appBarTheme.textTheme?.headline6 ?? theme.primaryTextTheme.headline6 @@ -951,7 +953,7 @@ class _AppBarState extends State { } final Brightness overlayStyleBrightness = widget.brightness ?? appBarTheme.brightness ?? colorScheme.brightness; - final SystemUiOverlayStyle overlayStyle = widget.backwardsCompatibility + final SystemUiOverlayStyle overlayStyle = backwardsCompatibility ? (overlayStyleBrightness == Brightness.dark ? SystemUiOverlayStyle.light : SystemUiOverlayStyle.dark) : widget.systemOverlayStyle ?? appBarTheme.systemOverlayStyle diff --git a/packages/flutter/lib/src/material/app_bar_theme.dart b/packages/flutter/lib/src/material/app_bar_theme.dart index aa67a74d64..7263235d00 100644 --- a/packages/flutter/lib/src/material/app_bar_theme.dart +++ b/packages/flutter/lib/src/material/app_bar_theme.dart @@ -42,6 +42,7 @@ class AppBarTheme with Diagnosticable { this.toolbarTextStyle, this.titleTextStyle, this.systemOverlayStyle, + this.backwardsCompatibility, }); /// This property is obsolete, please use [systemOverlayStyle] instead. @@ -161,6 +162,10 @@ class AppBarTheme with Diagnosticable { /// property in all descendant [AppBar] widgets. final SystemUiOverlayStyle? systemOverlayStyle; + /// Overrides the default value of [AppBar.backwardsCompatibility] + /// property in all descendant [AppBar] widgets. + final bool? backwardsCompatibility; + /// Creates a copy of this object with the given fields replaced with the /// new values. AppBarTheme copyWith({ @@ -178,6 +183,7 @@ class AppBarTheme with Diagnosticable { TextStyle? toolbarTextStyle, TextStyle? titleTextStyle, SystemUiOverlayStyle? systemOverlayStyle, + bool? backwardsCompatibility, }) { return AppBarTheme( brightness: brightness ?? this.brightness, @@ -194,6 +200,7 @@ class AppBarTheme with Diagnosticable { toolbarTextStyle: toolbarTextStyle ?? this.toolbarTextStyle, titleTextStyle: titleTextStyle ?? this.titleTextStyle, systemOverlayStyle: systemOverlayStyle ?? this.systemOverlayStyle, + backwardsCompatibility: backwardsCompatibility ?? this.backwardsCompatibility, ); } @@ -224,6 +231,7 @@ class AppBarTheme with Diagnosticable { toolbarTextStyle: TextStyle.lerp(a?.toolbarTextStyle, b?.toolbarTextStyle, t), titleTextStyle: TextStyle.lerp(a?.titleTextStyle, b?.titleTextStyle, t), systemOverlayStyle: t < 0.5 ? a?.systemOverlayStyle : b?.systemOverlayStyle, + backwardsCompatibility: t < 0.5 ? a?.backwardsCompatibility : b?.backwardsCompatibility, ); } @@ -244,6 +252,7 @@ class AppBarTheme with Diagnosticable { toolbarTextStyle, titleTextStyle, systemOverlayStyle, + backwardsCompatibility, ); } @@ -267,7 +276,8 @@ class AppBarTheme with Diagnosticable { && other.titleSpacing == titleSpacing && other.toolbarTextStyle == toolbarTextStyle && other.titleTextStyle == titleTextStyle - && other.systemOverlayStyle == systemOverlayStyle; + && other.systemOverlayStyle == systemOverlayStyle + && other.backwardsCompatibility == backwardsCompatibility; } @override @@ -286,5 +296,6 @@ class AppBarTheme with Diagnosticable { properties.add(DiagnosticsProperty('titleSpacing', titleSpacing, defaultValue: null)); properties.add(DiagnosticsProperty('toolbarTextStyle', toolbarTextStyle, defaultValue: null)); properties.add(DiagnosticsProperty('titleTextStyle', titleTextStyle, defaultValue: null)); + properties.add(DiagnosticsProperty('backwardsCompatibility', backwardsCompatibility, defaultValue: null)); } } diff --git a/packages/flutter/test/material/app_bar_test.dart b/packages/flutter/test/material/app_bar_test.dart index 7d93e92b1e..799d00ff02 100644 --- a/packages/flutter/test/material/app_bar_test.dart +++ b/packages/flutter/test/material/app_bar_test.dart @@ -2273,4 +2273,90 @@ void main() { final NavigationToolbar navToolBar = tester.widget(find.byType(NavigationToolbar)); expect(navToolBar.middleSpacing, NavigationToolbar.kMiddleSpacing); }); + + testWidgets('AppBar foregroundColor and backgroundColor', (WidgetTester tester) async { + const Color foregroundColor = Color(0xff00ff00); + const Color backgroundColor = Color(0xff00ffff); + final Key leadingIconKey = UniqueKey(); + final Key actionIconKey = UniqueKey(); + + await tester.pumpWidget( + MaterialApp( + home: Scaffold( + appBar: AppBar( + backwardsCompatibility: false, + foregroundColor: foregroundColor, + backgroundColor: backgroundColor, + leading: Icon(Icons.add_circle, key: leadingIconKey), + title: const Text('title'), + actions: [Icon(Icons.add_circle, key: actionIconKey), const Text('action')], + ), + ), + ), + ); + + final Material appBarMaterial = tester.widget( + find.descendant( + of: find.byType(AppBar), + matching: find.byType(Material), + ), + ); + expect(appBarMaterial.color, backgroundColor); + + final TextStyle titleTextStyle = tester.widget( + find.ancestor(of: find.text('title'), matching: find.byType(DefaultTextStyle)).first, + ).style; + expect(titleTextStyle.color, foregroundColor); + + final IconThemeData leadingIconTheme = tester.widget( + find.ancestor(of: find.byKey(leadingIconKey), matching: find.byType(IconTheme)).first, + ).data; + expect(leadingIconTheme.color, foregroundColor); + + final IconThemeData actionIconTheme = tester.widget( + find.ancestor(of: find.byKey(actionIconKey), matching: find.byType(IconTheme)).first, + ).data; + expect(actionIconTheme.color, foregroundColor); + }); + + + testWidgets('AppBarTheme.backwardsCompatibility', (WidgetTester tester) async { + const Color foregroundColor = Color(0xff00ff00); + final Key leadingIconKey = UniqueKey(); + final Key actionIconKey = UniqueKey(); + + await tester.pumpWidget( + MaterialApp( + theme: ThemeData.light().copyWith( + appBarTheme: const AppBarTheme( + backwardsCompatibility: false, + ), + ), + home: Scaffold( + appBar: AppBar( + foregroundColor: foregroundColor, // only applies if backwardsCompatibility is false + leading: Icon(Icons.add_circle, key: leadingIconKey), + title: const Text('title'), + actions: [Icon(Icons.add_circle, key: actionIconKey), const Text('action')], + ), + ), + ), + ); + + final TextStyle titleTextStyle = tester.widget( + find.ancestor(of: find.text('title'), matching: find.byType(DefaultTextStyle)).first, + ).style; + expect(titleTextStyle.color, foregroundColor); + + final IconThemeData leadingIconTheme = tester.widget( + find.ancestor(of: find.byKey(leadingIconKey), matching: find.byType(IconTheme)).first, + ).data; + expect(leadingIconTheme.color, foregroundColor); + + final IconThemeData actionIconTheme = tester.widget( + find.ancestor(of: find.byKey(actionIconKey), matching: find.byType(IconTheme)).first, + ).data; + expect(actionIconTheme.color, foregroundColor); + }); + } diff --git a/packages/flutter/test/material/app_bar_theme_test.dart b/packages/flutter/test/material/app_bar_theme_test.dart index 5d7e1f6fc7..5759777ea6 100644 --- a/packages/flutter/test/material/app_bar_theme_test.dart +++ b/packages/flutter/test/material/app_bar_theme_test.dart @@ -440,6 +440,7 @@ void main() { testWidgets('AppBarTheme implements debugFillProperties', (WidgetTester tester) async { final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder(); const AppBarTheme( + backwardsCompatibility: false, brightness: Brightness.dark, color: Color(0xff000001), elevation: 8.0, @@ -460,6 +461,7 @@ void main() { 'shadowColor: Color(0xff000002)', 'centerTitle: true', 'titleSpacing: 40.0', + 'backwardsCompatibility: false', ]); // On the web, Dart doubles and ints are backed by the same kind of object because