From 0e17b235db1b8d09b8c0b9b25281c6b5ea7225b9 Mon Sep 17 00:00:00 2001 From: tahatesser Date: Mon, 7 Nov 2022 15:29:25 +0200 Subject: [PATCH 1/2] Update `CircleAvatar` to support Material 3 --- .../lib/src/material/circle_avatar.dart | 16 +++- .../test/material/circle_avatar_test.dart | 91 ++++++++++++------- 2 files changed, 70 insertions(+), 37 deletions(-) diff --git a/packages/flutter/lib/src/material/circle_avatar.dart b/packages/flutter/lib/src/material/circle_avatar.dart index 61faac64fd8f94..a2d7a84f6a574a 100644 --- a/packages/flutter/lib/src/material/circle_avatar.dart +++ b/packages/flutter/lib/src/material/circle_avatar.dart @@ -84,7 +84,8 @@ class CircleAvatar extends StatelessWidget { /// The color with which to fill the circle. Changing the background /// color will cause the avatar to animate to the new color. /// - /// If a [backgroundColor] is not specified, the theme's + /// If a [backgroundColor] is not specified and [ThemeData.useMaterial3] is true, + /// [ColorScheme.primaryContainer] will be used, otherwise the theme's /// [ThemeData.primaryColorLight] is used with dark foreground colors, and /// [ThemeData.primaryColorDark] with light foreground colors. final Color? backgroundColor; @@ -94,7 +95,9 @@ class CircleAvatar extends StatelessWidget { /// Defaults to the primary text theme color if no [backgroundColor] is /// specified. /// - /// Defaults to [ThemeData.primaryColorLight] for dark background colors, and + /// If a [foregroundColor] is not specified and [ThemeData.useMaterial3] is true, + /// [ColorScheme.onPrimaryContainer] will be used, otherwise the theme's + /// [ThemeData.primaryColorLight] for dark background colors, and /// [ThemeData.primaryColorDark] for light background colors. final Color? foregroundColor; @@ -192,8 +195,11 @@ class CircleAvatar extends StatelessWidget { Widget build(BuildContext context) { assert(debugCheckHasMediaQuery(context)); final ThemeData theme = Theme.of(context); - TextStyle textStyle = theme.primaryTextTheme.titleMedium!.copyWith(color: foregroundColor); - Color? effectiveBackgroundColor = backgroundColor; + final Color? effectiveForegroundColor = foregroundColor + ?? (theme.useMaterial3 ? theme.colorScheme.onPrimaryContainer : null); + TextStyle textStyle = theme.primaryTextTheme.titleMedium!.copyWith(color: effectiveForegroundColor); + Color? effectiveBackgroundColor = backgroundColor + ?? (theme.useMaterial3 ? theme.colorScheme.primaryContainer : null); if (effectiveBackgroundColor == null) { switch (ThemeData.estimateBrightnessForColor(textStyle.color!)) { case Brightness.dark: @@ -203,7 +209,7 @@ class CircleAvatar extends StatelessWidget { effectiveBackgroundColor = theme.primaryColorDark; break; } - } else if (foregroundColor == null) { + } else if (effectiveForegroundColor == null) { switch (ThemeData.estimateBrightnessForColor(backgroundColor!)) { case Brightness.dark: textStyle = textStyle.copyWith(color: theme.primaryColorLight); diff --git a/packages/flutter/test/material/circle_avatar_test.dart b/packages/flutter/test/material/circle_avatar_test.dart index 4a7f534807158e..9249f4344bb1e5 100644 --- a/packages/flutter/test/material/circle_avatar_test.dart +++ b/packages/flutter/test/material/circle_avatar_test.dart @@ -144,36 +144,8 @@ void main() { expect(paragraph.text.style!.color, equals(foregroundColor)); }); - testWidgets('CircleAvatar with light theme', (WidgetTester tester) async { - final ThemeData theme = ThemeData( - primaryColor: Colors.grey.shade100, - primaryColorBrightness: Brightness.light, - ); - await tester.pumpWidget( - wrap( - child: Theme( - data: theme, - child: const CircleAvatar( - child: Text('Z'), - ), - ), - ), - ); - - final RenderConstrainedBox box = tester.renderObject(find.byType(CircleAvatar)); - final RenderDecoratedBox child = box.child! as RenderDecoratedBox; - final BoxDecoration decoration = child.decoration as BoxDecoration; - expect(decoration.color, equals(theme.primaryColorLight)); - - final RenderParagraph paragraph = tester.renderObject(find.text('Z')); - expect(paragraph.text.style!.color, equals(theme.primaryTextTheme.titleLarge!.color)); - }); - - testWidgets('CircleAvatar with dark theme', (WidgetTester tester) async { - final ThemeData theme = ThemeData( - primaryColor: Colors.grey.shade800, - primaryColorBrightness: Brightness.dark, - ); + testWidgets('CircleAvatar default colors', (WidgetTester tester) async { + final ThemeData theme = ThemeData(useMaterial3: true); await tester.pumpWidget( wrap( child: Theme( @@ -188,10 +160,10 @@ void main() { final RenderConstrainedBox box = tester.renderObject(find.byType(CircleAvatar)); final RenderDecoratedBox child = box.child! as RenderDecoratedBox; final BoxDecoration decoration = child.decoration as BoxDecoration; - expect(decoration.color, equals(theme.primaryColorDark)); + expect(decoration.color, equals(theme.colorScheme.primaryContainer)); final RenderParagraph paragraph = tester.renderObject(find.text('Z')); - expect(paragraph.text.style!.color, equals(theme.primaryTextTheme.titleLarge!.color)); + expect(paragraph.text.style!.color, equals(theme.colorScheme.onPrimaryContainer)); }); testWidgets('CircleAvatar text does not expand with textScaleFactor', (WidgetTester tester) async { @@ -306,6 +278,61 @@ void main() { final RenderParagraph paragraph = tester.renderObject(find.text('Z')); expect(paragraph.text.style!.color, equals(ThemeData.fallback().primaryColorLight)); }); + + group('Material 2', () { + // Tests that are only relevant for Material 2. Once ThemeData.useMaterial3 + // is turned on by default, these tests can be removed. + + testWidgets('CircleAvatar default colors with light theme', (WidgetTester tester) async { + final ThemeData theme = ThemeData( + primaryColor: Colors.grey.shade100, + primaryColorBrightness: Brightness.light, + ); + await tester.pumpWidget( + wrap( + child: Theme( + data: theme, + child: const CircleAvatar( + child: Text('Z'), + ), + ), + ), + ); + + final RenderConstrainedBox box = tester.renderObject(find.byType(CircleAvatar)); + final RenderDecoratedBox child = box.child! as RenderDecoratedBox; + final BoxDecoration decoration = child.decoration as BoxDecoration; + expect(decoration.color, equals(theme.primaryColorLight)); + + final RenderParagraph paragraph = tester.renderObject(find.text('Z')); + expect(paragraph.text.style!.color, equals(theme.primaryTextTheme.titleLarge!.color)); + }); + + testWidgets('CircleAvatar default colors with dark theme', (WidgetTester tester) async { + final ThemeData theme = ThemeData( + primaryColor: Colors.grey.shade800, + primaryColorBrightness: Brightness.dark, + ); + await tester.pumpWidget( + wrap( + child: Theme( + data: theme, + child: const CircleAvatar( + child: Text('Z'), + ), + ), + ), + ); + + final RenderConstrainedBox box = tester.renderObject(find.byType(CircleAvatar)); + final RenderDecoratedBox child = box.child! as RenderDecoratedBox; + final BoxDecoration decoration = child.decoration as BoxDecoration; + expect(decoration.color, equals(theme.primaryColorDark)); + + final RenderParagraph paragraph = tester.renderObject(find.text('Z')); + expect(paragraph.text.style!.color, equals(theme.primaryTextTheme.titleLarge!.color)); + }); + }); } Widget wrap({ required Widget child }) { From c46c7d62d3845bda078dac686de1d0050d9b9e7f Mon Sep 17 00:00:00 2001 From: tahatesser Date: Wed, 9 Nov 2022 11:22:29 +0200 Subject: [PATCH 2/2] Update text style --- packages/flutter/lib/src/material/circle_avatar.dart | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/flutter/lib/src/material/circle_avatar.dart b/packages/flutter/lib/src/material/circle_avatar.dart index a2d7a84f6a574a..11775c4500c4d8 100644 --- a/packages/flutter/lib/src/material/circle_avatar.dart +++ b/packages/flutter/lib/src/material/circle_avatar.dart @@ -197,7 +197,10 @@ class CircleAvatar extends StatelessWidget { final ThemeData theme = Theme.of(context); final Color? effectiveForegroundColor = foregroundColor ?? (theme.useMaterial3 ? theme.colorScheme.onPrimaryContainer : null); - TextStyle textStyle = theme.primaryTextTheme.titleMedium!.copyWith(color: effectiveForegroundColor); + final TextStyle effectiveTextStyle = theme.useMaterial3 + ? theme.textTheme.titleMedium! + : theme.primaryTextTheme.titleMedium!; + TextStyle textStyle = effectiveTextStyle.copyWith(color: effectiveForegroundColor); Color? effectiveBackgroundColor = backgroundColor ?? (theme.useMaterial3 ? theme.colorScheme.primaryContainer : null); if (effectiveBackgroundColor == null) {