Unverified Commit d3dcd7d5 authored by Taha Tesser's avatar Taha Tesser Committed by GitHub

Update `CircleAvatar` to support Material 3 (#114812)

parent 92f10ed7
......@@ -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,14 @@ 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);
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) {
switch (ThemeData.estimateBrightnessForColor(textStyle.color!)) {
case Brightness.dark:
......@@ -203,7 +212,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);
......
......@@ -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 }) {
......
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