diff --git a/packages/flutter/lib/src/material/chip.dart b/packages/flutter/lib/src/material/chip.dart index 296adb6b26..82ff6c2fbb 100644 --- a/packages/flutter/lib/src/material/chip.dart +++ b/packages/flutter/lib/src/material/chip.dart @@ -225,8 +225,15 @@ abstract class DeletableChipAttributes { /// {@end-tool} VoidCallback? get onDeleted; - /// The [Color] for the delete icon. The default is based on the ambient - /// [IconThemeData.color]. + /// Used to define the delete icon's color with an [IconTheme] that + /// contains the icon. + /// + /// The default is `Color(0xde000000)` + /// (slightly transparent black) for light themes, and `Color(0xdeffffff)` + /// (slightly transparent white) for dark themes. + /// + /// The delete icon appears if [DeletableChipAttributes.onDeleted] is + /// non-null. Color? get deleteIconColor; /// Whether to use a tooltip on the chip's delete button showing the @@ -423,7 +430,8 @@ abstract class DisabledChipAttributes { /// Defaults to true. Cannot be null. bool get isEnabled; - /// Color to be used for the chip's background indicating that it is disabled. + /// The color used for the chip's background to indicate that it is not + /// enabled. /// /// The chip is disabled when [isEnabled] is false, or all three of /// [SelectableChipAttributes.onSelected], [TappableChipAttributes.onPressed], @@ -1708,25 +1716,35 @@ class _RawChipState extends State with MaterialStateMixin, TickerProvid widget.onPressed?.call(); } - OutlinedBorder _getShape(ChipThemeData theme) { + OutlinedBorder _getShape(ThemeData theme, ChipThemeData chipTheme, ChipThemeData chipDefaults) { final BorderSide? resolvedSide = MaterialStateProperty.resolveAs(widget.side, materialStates) - ?? MaterialStateProperty.resolveAs(theme.side, materialStates); + ?? MaterialStateProperty.resolveAs(chipTheme.side, materialStates) + ?? MaterialStateProperty.resolveAs(chipDefaults.side, materialStates); final OutlinedBorder resolvedShape = MaterialStateProperty.resolveAs(widget.shape, materialStates) - ?? MaterialStateProperty.resolveAs(theme.shape, materialStates) + ?? MaterialStateProperty.resolveAs(chipTheme.shape, materialStates) + ?? MaterialStateProperty.resolveAs(chipDefaults.shape, materialStates) ?? const StadiumBorder(); return resolvedShape.copyWith(side: resolvedSide); } /// Picks between three different colors, depending upon the state of two /// different animations. - Color? getBackgroundColor(ChipThemeData theme) { + Color? _getBackgroundColor(ThemeData theme, ChipThemeData chipTheme, ChipThemeData chipDefaults) { final ColorTween backgroundTween = ColorTween( - begin: widget.disabledColor ?? theme.disabledColor, - end: widget.backgroundColor ?? theme.backgroundColor, + begin: widget.disabledColor + ?? chipTheme.disabledColor + ?? theme.disabledColor, + end: widget.backgroundColor + ?? chipTheme.backgroundColor + ?? theme.chipTheme.backgroundColor + ?? chipDefaults.backgroundColor, ); final ColorTween selectTween = ColorTween( begin: backgroundTween.evaluate(enableController), - end: widget.selectedColor ?? theme.selectedColor, + end: widget.selectedColor + ?? chipTheme.selectedColor + ?? theme.chipTheme.selectedColor + ?? chipDefaults.selectedColor, ); return selectTween.evaluate(selectionFade); } @@ -1788,6 +1806,7 @@ class _RawChipState extends State with MaterialStateMixin, TickerProvid BuildContext context, ThemeData theme, ChipThemeData chipTheme, + ChipThemeData chipDefaults, ) { if (!hasDeleteButton) { return null; @@ -1796,7 +1815,9 @@ class _RawChipState extends State with MaterialStateMixin, TickerProvid container: true, button: true, child: _wrapWithTooltip( - tooltip: widget.useDeleteButtonTooltip ? widget.deleteButtonTooltipMessage ?? MaterialLocalizations.of(context).deleteButtonTooltip : null, + tooltip: widget.useDeleteButtonTooltip + ? widget.deleteButtonTooltipMessage ?? MaterialLocalizations.of(context).deleteButtonTooltip + : null, enabled: widget.onDeleted != null, child: InkWell( // Radius should be slightly less than the full size of the chip. @@ -1806,7 +1827,10 @@ class _RawChipState extends State with MaterialStateMixin, TickerProvid onTap: widget.isEnabled ? widget.onDeleted : null, child: IconTheme( data: theme.iconTheme.copyWith( - color: widget.deleteIconColor ?? chipTheme.deleteIconColor, + color: widget.deleteIconColor + ?? chipTheme.deleteIconColor + ?? theme.chipTheme.deleteIconColor + ?? chipDefaults.deleteIconColor, ), child: widget.deleteIcon, ), @@ -1838,19 +1862,53 @@ class _RawChipState extends State with MaterialStateMixin, TickerProvid final ThemeData theme = Theme.of(context); final ChipThemeData chipTheme = ChipTheme.of(context); + final Brightness brightness = chipTheme.brightness ?? theme.brightness; + final ChipThemeData chipDefaults = ChipThemeData.fromDefaults( + brightness: brightness, + secondaryColor: brightness == Brightness.dark ? Colors.tealAccent[200]! : theme.primaryColor, + labelStyle: theme.textTheme.bodyText1!, + ); final TextDirection? textDirection = Directionality.maybeOf(context); - final OutlinedBorder resolvedShape = _getShape(chipTheme); - final double elevation = widget.elevation ?? chipTheme.elevation ?? _defaultElevation; - final double pressElevation = widget.pressElevation ?? chipTheme.pressElevation ?? _defaultPressElevation; - final Color shadowColor = widget.shadowColor ?? chipTheme.shadowColor ?? _defaultShadowColor; - final Color selectedShadowColor = widget.selectedShadowColor ?? chipTheme.selectedShadowColor ?? _defaultShadowColor; - final Color? checkmarkColor = widget.checkmarkColor ?? chipTheme.checkmarkColor; - final bool showCheckmark = widget.showCheckmark ?? chipTheme.showCheckmark ?? true; + final OutlinedBorder resolvedShape = _getShape(theme, chipTheme, chipDefaults); - final TextStyle effectiveLabelStyle = chipTheme.labelStyle.merge(widget.labelStyle); + final double elevation = widget.elevation + ?? chipTheme.elevation + ?? theme.chipTheme.elevation + ?? _defaultElevation; + final double pressElevation = widget.pressElevation + ?? chipTheme.pressElevation + ?? theme.chipTheme.pressElevation + ?? _defaultPressElevation; + final Color shadowColor = widget.shadowColor + ?? chipTheme.shadowColor + ?? theme.chipTheme.shadowColor + ?? _defaultShadowColor; + final Color selectedShadowColor = widget.selectedShadowColor + ?? chipTheme.selectedShadowColor + ?? theme.chipTheme.selectedShadowColor + ?? _defaultShadowColor; + final Color? checkmarkColor = widget.checkmarkColor + ?? chipTheme.checkmarkColor + ?? theme.chipTheme.checkmarkColor; + final bool showCheckmark = widget.showCheckmark + ?? chipTheme.showCheckmark + ?? theme.chipTheme.showCheckmark + ?? true; + final EdgeInsetsGeometry padding = widget.padding + ?? chipTheme.padding + ?? theme.chipTheme.padding + ?? chipDefaults.padding!; + final TextStyle? labelStyle = widget.labelStyle + ?? chipTheme.labelStyle + ?? theme.chipTheme.labelStyle; + final EdgeInsetsGeometry labelPadding = widget.labelPadding + ?? chipTheme.labelPadding + ?? theme.chipTheme.labelPadding + ?? _defaultLabelPadding; + + final TextStyle effectiveLabelStyle = chipDefaults.labelStyle!.merge(labelStyle); final Color? resolvedLabelColor = MaterialStateProperty.resolveAs(effectiveLabelStyle.color, materialStates); final TextStyle resolvedLabelStyle = effectiveLabelStyle.copyWith(color: resolvedLabelColor); - final EdgeInsetsGeometry labelPadding = widget.labelPadding ?? chipTheme.labelPadding ?? _defaultLabelPadding; Widget result = Material( elevation: isTapping ? pressElevation : elevation, @@ -1874,7 +1932,7 @@ class _RawChipState extends State with MaterialStateMixin, TickerProvid return Container( decoration: ShapeDecoration( shape: resolvedShape, - color: getBackgroundColor(chipTheme), + color: _getBackgroundColor(theme, chipTheme, chipDefaults), ), child: child, ); @@ -1900,10 +1958,10 @@ class _RawChipState extends State with MaterialStateMixin, TickerProvid deleteIcon: AnimatedSwitcher( duration: _kDrawerDuration, switchInCurve: Curves.fastOutSlowIn, - child: _buildDeleteIcon(context, theme, chipTheme), + child: _buildDeleteIcon(context, theme, chipTheme, chipDefaults), ), - brightness: chipTheme.brightness, - padding: (widget.padding ?? chipTheme.padding).resolve(textDirection), + brightness: brightness, + padding: padding.resolve(textDirection), visualDensity: widget.visualDensity ?? theme.visualDensity, labelPadding: labelPadding.resolve(textDirection), showAvatar: hasAvatar, @@ -2572,6 +2630,7 @@ class _RenderChip extends RenderBox { overallSize.width + theme.padding.horizontal, overallSize.height + theme.padding.vertical, ); + return _ChipSizes( size: constraints.constrain(paddedSize), overall: overallSize, diff --git a/packages/flutter/lib/src/material/chip_theme.dart b/packages/flutter/lib/src/material/chip_theme.dart index de4796fadf..f12ecd2712 100644 --- a/packages/flutter/lib/src/material/chip_theme.dart +++ b/packages/flutter/lib/src/material/chip_theme.dart @@ -179,32 +179,25 @@ class ChipThemeData with Diagnosticable { /// This will rarely be used directly. It is used by [lerp] to /// create intermediate themes based on two themes. const ChipThemeData({ - required this.backgroundColor, + this.backgroundColor, this.deleteIconColor, - required this.disabledColor, - required this.selectedColor, - required this.secondarySelectedColor, + this.disabledColor, + this.selectedColor, + this.secondarySelectedColor, this.shadowColor, this.selectedShadowColor, this.showCheckmark, this.checkmarkColor, this.labelPadding, - required this.padding, + this.padding, this.side, this.shape, - required this.labelStyle, - required this.secondaryLabelStyle, - required this.brightness, + this.labelStyle, + this.secondaryLabelStyle, + this.brightness, this.elevation, this.pressElevation, - }) : assert(backgroundColor != null), - assert(disabledColor != null), - assert(selectedColor != null), - assert(secondarySelectedColor != null), - assert(padding != null), - assert(labelStyle != null), - assert(secondaryLabelStyle != null), - assert(brightness != null); + }); /// Generates a ChipThemeData from a brightness, a primary color, and a text /// style. @@ -267,91 +260,87 @@ class ChipThemeData with Diagnosticable { padding: padding, labelStyle: labelStyle, secondaryLabelStyle: secondaryLabelStyle, - brightness: brightness!, + brightness: brightness, ); } - /// Color to be used for the unselected, enabled chip's background. + /// Overrides the default for [ChipAttributes.backgroundColor] + /// which is used for unselected, enabled chip backgrounds. /// - /// The default is light grey. - final Color backgroundColor; + /// This property applies to [ActionChip], [Chip], [ChoiceChip], + /// [FilterChip], [InputChip], [RawChip]. + final Color? backgroundColor; - /// The [Color] for the delete icon. The default is Color(0xde000000) - /// (slightly transparent black) for light themes, and Color(0xdeffffff) - /// (slightly transparent white) for dark themes. + /// Overrides the default for [DeletableChipAttributes.deleteIconColor]. /// - /// May be set to null, in which case the ambient [IconThemeData.color] is used. + /// This property applies to [Chip], [InputChip], [RawChip]. final Color? deleteIconColor; - /// Color to be used for the chip's background indicating that it is disabled. + /// Overrides the default for + /// [DisabledChipAttributes.disabledColor], the background color + /// which indicates that the chip is not enabled. /// - /// The chip is disabled when [DisabledChipAttributes.isEnabled] is false, or - /// all three of [SelectableChipAttributes.onSelected], - /// [TappableChipAttributes.onPressed], and - /// [DeletableChipAttributes.onDeleted] are null. - /// - /// It defaults to [Colors.black38]. - final Color disabledColor; + /// This property applies to [ChoiceChip], [FilterChip], + /// [InputChip], [RawChip]. + final Color? disabledColor; - /// Color to be used for the chip's background, indicating that it is - /// selected. + /// Overrides the default for + /// [SelectableChipAttributes.selectedColor], the background color + /// that indicates that the chip is selected. /// - /// The chip is selected when [SelectableChipAttributes.selected] is true. - final Color selectedColor; + /// This property applies to [ChoiceChip], [FilterChip], + /// [InputChip], [RawChip]. + final Color? selectedColor; - /// An alternate color to be used for the chip's background, indicating that - /// it is selected. For example, this color is used by [ChoiceChip] when the - /// choice is selected. - /// - /// The chip is selected when [SelectableChipAttributes.selected] is true. - final Color secondarySelectedColor; + /// Overrides the default for [ChoiceChip.selectedColor], the + /// background color that indicates that the chip is selected. + final Color? secondarySelectedColor; - /// Color of the chip's shadow when the elevation is greater than 0. + /// Overrides the default for [ChipAttributes.shadowColor], the + /// Color of the chip's shadow when its elevation is greater than 0. /// - /// If null, the chip defaults to [Colors.black]. - /// - /// See also: - /// - /// * [selectedShadowColor] + /// This property applies to [ActionChip], [Chip], [ChoiceChip], + /// [FilterChip], [InputChip], [RawChip]. final Color? shadowColor; - /// Color of the chip's shadow when the elevation is greater than 0 and the - /// chip is selected. + /// Overrides the default for + /// [SelectableChipAttributes.selectedShadowColor], the Color of the + /// chip's shadow when its elevation is greater than 0 and the chip + /// is selected. /// - /// If null, the chip defaults to [Colors.black]. - /// - /// See also: - /// - /// * [shadowColor] + /// This property applies to [ChoiceChip], [FilterChip], + /// [InputChip], [RawChip]. final Color? selectedShadowColor; - /// Whether or not to show a check mark when [SelectableChipAttributes.selected] is true. + /// Overrides the default for + /// [CheckmarkableChipAttributes.showCheckmark], which indicates if + /// a check mark should be shown. /// - /// For instance, the [ChoiceChip] sets this to false so that it can be - /// selected without showing the check mark. - /// - /// Defaults to true. + /// This property applies to [FilterChip], [InputChip], [RawChip]. final bool? showCheckmark; - /// Color of the chip's check mark when a check mark is visible. + /// Overrides the default for + /// [CheckmarkableChipAttributes.checkmarkColor]. /// - /// This will override the color set by the platform's brightness setting. + /// This property applies to [FilterChip], [InputChip], [RawChip]. final Color? checkmarkColor; - /// The padding around the [Chip.label] widget. + /// Overrides the default for [ChipAttributes.labelPadding], + /// the padding around the chip's label widget. /// - /// By default, this is 4 logical pixels at the beginning and the end of the - /// label, and zero on top and bottom. + /// This property applies to [ActionChip], [Chip], [ChoiceChip], + /// [FilterChip], [InputChip], [RawChip]. final EdgeInsetsGeometry? labelPadding; - /// The padding between the contents of the chip and the outside [shape]. + /// Overrides the default for [ChipAttributes.padding], + /// the padding between the contents of the chip and the outside [shape]. /// - /// Defaults to 4 logical pixels on all sides. - final EdgeInsetsGeometry padding; + /// This property applies to [ActionChip], [Chip], [ChoiceChip], + /// [FilterChip], [InputChip], [RawChip]. + final EdgeInsetsGeometry? padding; - /// The color and weight of the chip's outline. - /// - /// If null, the chip defaults to the border side of [shape]. + /// Overrides the default for [ChipAttributes.side], + /// the color and weight of the chip's outline. /// /// This value is combined with [shape] to create a shape decorated with an /// outline. If it is a [MaterialStateBorderSide], @@ -363,11 +352,13 @@ class ChipThemeData with Diagnosticable { /// * [MaterialState.hovered]. /// * [MaterialState.focused]. /// * [MaterialState.pressed]. + /// + /// This property applies to [ActionChip], [Chip], [ChoiceChip], + /// [FilterChip], [InputChip], [RawChip]. final BorderSide? side; - /// The border to draw around the chip. - /// - /// If null, the chip defaults to a [StadiumBorder]. + /// Overrides the default for [ChipAttributes.shape], + /// the shape of border to draw around the chip. /// /// This shape is combined with [side] to create a shape decorated with an /// outline. If it is a [MaterialStateOutlinedBorder], @@ -379,34 +370,45 @@ class ChipThemeData with Diagnosticable { /// * [MaterialState.hovered]. /// * [MaterialState.focused]. /// * [MaterialState.pressed]. + /// + /// This property applies to [ActionChip], [Chip], [ChoiceChip], + /// [FilterChip], [InputChip], [RawChip]. final OutlinedBorder? shape; - /// The style to be applied to the chip's label. + /// Overrides the default for [ChipAttributes.labelStyle], + /// the style of the [DefaultTextStyle] that contains the + /// chip's label. /// /// This only has an effect on label widgets that respect the /// [DefaultTextStyle], such as [Text]. - final TextStyle labelStyle; + /// + /// This property applies to [ActionChip], [Chip], + /// [FilterChip], [InputChip], [RawChip]. + final TextStyle? labelStyle; - /// An alternate style to be applied to the chip's label. For example, this - /// style is applied to the text of a selected [ChoiceChip]. + /// Overrides the default for [ChoiceChip.labelStyle], + /// the style of the [DefaultTextStyle] that contains the + /// chip's label. /// /// This only has an effect on label widgets that respect the /// [DefaultTextStyle], such as [Text]. - final TextStyle secondaryLabelStyle; + final TextStyle? secondaryLabelStyle; - /// The brightness setting for this theme. - /// - /// This affects various base material color choices in the chip rendering. - final Brightness brightness; + /// Overrides the default value for all chips which affects various base + /// material color choices in the chip rendering. + final Brightness? brightness; - /// The elevation to be applied to the chip. + /// Overrides the default for [ChipAttributes.elevation], + /// the elevation of the chip's [Material]. /// - /// If null, the chip defaults to 0. + /// This property applies to [ActionChip], [Chip], [ChoiceChip], + /// [FilterChip], [InputChip], [RawChip]. final double? elevation; - /// The elevation to be applied to the chip during the press motion. + /// Overrides the default for [TappableChipAttributes.pressElevation], + /// the elevation of the chip's [Material] during a "press" or tap down. /// - /// If null, the chip defaults to 8. + /// This property applies to [ActionChip], [InputChip], [RawChip]. final double? pressElevation; /// Creates a copy of this object but with the given fields replaced with the @@ -461,20 +463,20 @@ class ChipThemeData with Diagnosticable { if (a == null && b == null) return null; return ChipThemeData( - backgroundColor: Color.lerp(a?.backgroundColor, b?.backgroundColor, t)!, + backgroundColor: Color.lerp(a?.backgroundColor, b?.backgroundColor, t), deleteIconColor: Color.lerp(a?.deleteIconColor, b?.deleteIconColor, t), - disabledColor: Color.lerp(a?.disabledColor, b?.disabledColor, t)!, - selectedColor: Color.lerp(a?.selectedColor, b?.selectedColor, t)!, - secondarySelectedColor: Color.lerp(a?.secondarySelectedColor, b?.secondarySelectedColor, t)!, + disabledColor: Color.lerp(a?.disabledColor, b?.disabledColor, t), + selectedColor: Color.lerp(a?.selectedColor, b?.selectedColor, t), + secondarySelectedColor: Color.lerp(a?.secondarySelectedColor, b?.secondarySelectedColor, t), shadowColor: Color.lerp(a?.shadowColor, b?.shadowColor, t), selectedShadowColor: Color.lerp(a?.selectedShadowColor, b?.selectedShadowColor, t), checkmarkColor: Color.lerp(a?.checkmarkColor, b?.checkmarkColor, t), labelPadding: EdgeInsetsGeometry.lerp(a?.labelPadding, b?.labelPadding, t), - padding: EdgeInsetsGeometry.lerp(a?.padding, b?.padding, t)!, + padding: EdgeInsetsGeometry.lerp(a?.padding, b?.padding, t), side: _lerpSides(a?.side, b?.side, t), shape: _lerpShapes(a?.shape, b?.shape, t), - labelStyle: TextStyle.lerp(a?.labelStyle, b?.labelStyle, t)!, - secondaryLabelStyle: TextStyle.lerp(a?.secondaryLabelStyle, b?.secondaryLabelStyle, t)!, + labelStyle: TextStyle.lerp(a?.labelStyle, b?.labelStyle, t), + secondaryLabelStyle: TextStyle.lerp(a?.secondaryLabelStyle, b?.secondaryLabelStyle, t), brightness: t < 0.5 ? a?.brightness ?? Brightness.light : b?.brightness ?? Brightness.light, elevation: lerpDouble(a?.elevation, b?.elevation, t), pressElevation: lerpDouble(a?.pressElevation, b?.pressElevation, t), @@ -553,28 +555,22 @@ class ChipThemeData with Diagnosticable { @override void debugFillProperties(DiagnosticPropertiesBuilder properties) { super.debugFillProperties(properties); - final ThemeData defaultTheme = ThemeData.fallback(); - final ChipThemeData defaultData = ChipThemeData.fromDefaults( - secondaryColor: defaultTheme.primaryColor, - brightness: defaultTheme.brightness, - labelStyle: defaultTheme.textTheme.bodyText1!, - ); - properties.add(ColorProperty('backgroundColor', backgroundColor, defaultValue: defaultData.backgroundColor)); - properties.add(ColorProperty('deleteIconColor', deleteIconColor, defaultValue: defaultData.deleteIconColor)); - properties.add(ColorProperty('disabledColor', disabledColor, defaultValue: defaultData.disabledColor)); - properties.add(ColorProperty('selectedColor', selectedColor, defaultValue: defaultData.selectedColor)); - properties.add(ColorProperty('secondarySelectedColor', secondarySelectedColor, defaultValue: defaultData.secondarySelectedColor)); - properties.add(ColorProperty('shadowColor', shadowColor, defaultValue: defaultData.shadowColor)); - properties.add(ColorProperty('selectedShadowColor', selectedShadowColor, defaultValue: defaultData.selectedShadowColor)); - properties.add(ColorProperty('checkMarkColor', checkmarkColor, defaultValue: defaultData.checkmarkColor)); - properties.add(DiagnosticsProperty('labelPadding', labelPadding, defaultValue: defaultData.labelPadding)); - properties.add(DiagnosticsProperty('padding', padding, defaultValue: defaultData.padding)); - properties.add(DiagnosticsProperty('side', side, defaultValue: defaultData.side)); - properties.add(DiagnosticsProperty('shape', shape, defaultValue: defaultData.shape)); - properties.add(DiagnosticsProperty('labelStyle', labelStyle, defaultValue: defaultData.labelStyle)); - properties.add(DiagnosticsProperty('secondaryLabelStyle', secondaryLabelStyle, defaultValue: defaultData.secondaryLabelStyle)); - properties.add(EnumProperty('brightness', brightness, defaultValue: defaultData.brightness)); - properties.add(DoubleProperty('elevation', elevation, defaultValue: defaultData.elevation)); - properties.add(DoubleProperty('pressElevation', pressElevation, defaultValue: defaultData.pressElevation)); + properties.add(ColorProperty('backgroundColor', backgroundColor, defaultValue: null)); + properties.add(ColorProperty('deleteIconColor', deleteIconColor, defaultValue: null)); + properties.add(ColorProperty('disabledColor', disabledColor, defaultValue: null)); + properties.add(ColorProperty('selectedColor', selectedColor, defaultValue: null)); + properties.add(ColorProperty('secondarySelectedColor', secondarySelectedColor, defaultValue: null)); + properties.add(ColorProperty('shadowColor', shadowColor, defaultValue: null)); + properties.add(ColorProperty('selectedShadowColor', selectedShadowColor, defaultValue: null)); + properties.add(ColorProperty('checkMarkColor', checkmarkColor, defaultValue: null)); + properties.add(DiagnosticsProperty('labelPadding', labelPadding, defaultValue: null)); + properties.add(DiagnosticsProperty('padding', padding, defaultValue: null)); + properties.add(DiagnosticsProperty('side', side, defaultValue: null)); + properties.add(DiagnosticsProperty('shape', shape, defaultValue: null)); + properties.add(DiagnosticsProperty('labelStyle', labelStyle, defaultValue: null)); + properties.add(DiagnosticsProperty('secondaryLabelStyle', secondaryLabelStyle, defaultValue: null)); + properties.add(EnumProperty('brightness', brightness, defaultValue: null)); + properties.add(DoubleProperty('elevation', elevation, defaultValue: null)); + properties.add(DoubleProperty('pressElevation', pressElevation, defaultValue: null)); } } diff --git a/packages/flutter/lib/src/material/theme_data.dart b/packages/flutter/lib/src/material/theme_data.dart index 6c15ff1699..873f271fed 100644 --- a/packages/flutter/lib/src/material/theme_data.dart +++ b/packages/flutter/lib/src/material/theme_data.dart @@ -466,11 +466,7 @@ class ThemeData with Diagnosticable { bottomSheetTheme ??= const BottomSheetThemeData(); buttonBarTheme ??= const ButtonBarThemeData(); cardTheme ??= const CardTheme(); - chipTheme ??= ChipThemeData.fromDefaults( - secondaryColor: isDark ? Colors.tealAccent[200]! : primaryColor, - brightness: colorScheme.brightness, - labelStyle: textTheme.bodyText1!, - ); + chipTheme ??= const ChipThemeData(); checkboxTheme ??= const CheckboxThemeData(); dataTableTheme ??= const DataTableThemeData(); dialogTheme ??= const DialogTheme(); diff --git a/packages/flutter/test/material/chip_test.dart b/packages/flutter/test/material/chip_test.dart index 6fbe965543..f4e0a7ced3 100644 --- a/packages/flutter/test/material/chip_test.dart +++ b/packages/flutter/test/material/chip_test.dart @@ -270,6 +270,80 @@ Finder findTooltipContainer(String tooltipText) { } void main() { + testWidgets('Chip defaults', (WidgetTester tester) async { + Widget buildFrame(Brightness brightness) { + return MaterialApp( + theme: ThemeData(brightness: brightness), + home: Scaffold( + body: Center( + child: Chip( + avatar: const CircleAvatar(child: Text('A')), + label: const Text('Chip A'), + onDeleted: () { }, + ), + ), + ), + ); + } + + await tester.pumpWidget(buildFrame(Brightness.light)); + expect(getMaterialBox(tester), paints..path(color: const Color(0x1f000000))); + expect(tester.getSize(find.byType(Chip)), const Size(156.0, 48.0)); + expect(getMaterial(tester).color, null); + expect(getMaterial(tester).elevation, 0); + expect(getMaterial(tester).shape, const StadiumBorder()); + expect(getIconData(tester).color?.value, 0xffffffff); + expect(getIconData(tester).opacity, null); + expect(getIconData(tester).size, null); + expect(getLabelStyle(tester).style.color?.value, 0xde000000); + + await tester.pumpWidget(buildFrame(Brightness.dark)); + await tester.pumpAndSettle(); // Theme transition animation + expect(getMaterialBox(tester), paints..path(color: const Color(0x1fffffff))); + expect(tester.getSize(find.byType(Chip)), const Size(156.0, 48.0)); + expect(getMaterial(tester).color, null); + expect(getMaterial(tester).elevation, 0); + expect(getMaterial(tester).shape, const StadiumBorder()); + expect(getIconData(tester).color?.value, 0xffffffff); + expect(getIconData(tester).opacity, null); + expect(getIconData(tester).size, null); + expect(getLabelStyle(tester).style.color?.value, 0xffffffff); + }); + + testWidgets('ChoiceChip defaults', (WidgetTester tester) async { + Widget buildFrame(Brightness brightness) { + return MaterialApp( + theme: ThemeData(brightness: brightness), + home: const Scaffold( + body: Center( + child: ChoiceChip( + label: Text('Chip A'), + selected: true, + ), + ), + ), + ); + } + + await tester.pumpWidget(buildFrame(Brightness.light)); + expect(getMaterialBox(tester), paints..path(color: const Color(0x3d000000))); + expect(tester.getSize(find.byType(ChoiceChip)), const Size(108.0, 48.0)); + expect(getMaterial(tester).color, null); + expect(getMaterial(tester).elevation, 0); + expect(getMaterial(tester).shape, const StadiumBorder()); + expect(getLabelStyle(tester).style.color?.value, 0xde000000); + + await tester.pumpWidget(buildFrame(Brightness.dark)); + await tester.pumpAndSettle(); // Theme transition animation + expect(getMaterialBox(tester), paints..path(color: const Color(0x3dffffff))); + expect(tester.getSize(find.byType(ChoiceChip)), const Size(108.0, 48.0)); + expect(getMaterial(tester).color, null); + expect(getMaterial(tester).elevation, 0); + expect(getMaterial(tester).shape, const StadiumBorder()); + expect(getLabelStyle(tester).style.color?.value, 0xdeffffff); + }); + + testWidgets('Chip control test', (WidgetTester tester) async { final FeedbackTester feedback = FeedbackTester(); final List deletedChipLabels = []; @@ -1697,7 +1771,11 @@ void main() { platform: TargetPlatform.android, primarySwatch: Colors.blue, ); - final ChipThemeData defaultChipTheme = themeData.chipTheme; + final ChipThemeData defaultChipTheme = ChipThemeData.fromDefaults( + brightness: themeData.brightness, + secondaryColor: Colors.blue, + labelStyle: themeData.textTheme.bodyText1!, + ); bool value = false; Widget buildApp({ ChipThemeData? chipTheme, diff --git a/packages/flutter/test/material/chip_theme_test.dart b/packages/flutter/test/material/chip_theme_test.dart index 2fbdd7792c..b805e86dbf 100644 --- a/packages/flutter/test/material/chip_theme_test.dart +++ b/packages/flutter/test/material/chip_theme_test.dart @@ -39,129 +39,266 @@ IconThemeData getIconData(WidgetTester tester) { DefaultTextStyle getLabelStyle(WidgetTester tester) { return tester.widget( - find - .descendant( - of: find.byType(RawChip), - matching: find.byType(DefaultTextStyle), - ) - .last, + find.descendant( + of: find.byType(RawChip), + matching: find.byType(DefaultTextStyle), + ).last, ); } void main() { - testWidgets('Chip theme is built by ThemeData', (WidgetTester tester) async { - final ThemeData theme = ThemeData( - platform: TargetPlatform.android, - primarySwatch: Colors.red, - ); - final ChipThemeData chipTheme = theme.chipTheme; + test('ChipThemeData copyWith, ==, hashCode basics', () { + expect(const ChipThemeData(), const ChipThemeData().copyWith()); + expect(const ChipThemeData().hashCode, const ChipThemeData().copyWith().hashCode); + }); + test('ChipThemeData defaults', () { + const ChipThemeData themeData = ChipThemeData(); + expect(themeData.backgroundColor, null); + expect(themeData.deleteIconColor, null); + expect(themeData.disabledColor, null); + expect(themeData.selectedColor, null); + expect(themeData.secondarySelectedColor, null); + expect(themeData.shadowColor, null); + expect(themeData.selectedShadowColor, null); + expect(themeData.showCheckmark, null); + expect(themeData.checkmarkColor, null); + expect(themeData.labelPadding, null); + expect(themeData.padding, null); + expect(themeData.side, null); + expect(themeData.shape, null); + expect(themeData.labelStyle, null); + expect(themeData.secondaryLabelStyle, null); + expect(themeData.brightness, null); + expect(themeData.elevation, null); + expect(themeData.pressElevation, null); + }); + + testWidgets('Default ChipThemeData debugFillProperties', (WidgetTester tester) async { + final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder(); + const ChipThemeData().debugFillProperties(builder); + + final List description = builder.properties + .where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info)) + .map((DiagnosticsNode node) => node.toString()) + .toList(); + + expect(description, []); + }); + + testWidgets('ChipThemeData implements debugFillProperties', (WidgetTester tester) async { + final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder(); + const ChipThemeData( + backgroundColor: Color(0xfffffff0), + deleteIconColor: Color(0xfffffff1), + disabledColor: Color(0xfffffff2), + selectedColor: Color(0xfffffff3), + secondarySelectedColor: Color(0xfffffff4), + shadowColor: Color(0xfffffff5), + selectedShadowColor: Color(0xfffffff6), + showCheckmark: true, + checkmarkColor: Color(0xfffffff7), + labelPadding: EdgeInsets.all(1), + padding: EdgeInsets.all(2), + side: BorderSide(width: 10), + shape: RoundedRectangleBorder(), + labelStyle: TextStyle(fontSize: 10), + secondaryLabelStyle: TextStyle(fontSize: 20), + brightness: Brightness.dark, + elevation: 5, + pressElevation: 6, + ).debugFillProperties(builder); + + final List description = builder.properties + .where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info)) + .map((DiagnosticsNode node) => node.toString()) + .toList(); + + expect(description, [ + 'backgroundColor: Color(0xfffffff0)', + 'deleteIconColor: Color(0xfffffff1)', + 'disabledColor: Color(0xfffffff2)', + 'selectedColor: Color(0xfffffff3)', + 'secondarySelectedColor: Color(0xfffffff4)', + 'shadowColor: Color(0xfffffff5)', + 'selectedShadowColor: Color(0xfffffff6)', + 'checkMarkColor: Color(0xfffffff7)', + 'labelPadding: EdgeInsets.all(1.0)', + 'padding: EdgeInsets.all(2.0)', + 'side: BorderSide(Color(0xff000000), 10.0, BorderStyle.solid)', + 'shape: RoundedRectangleBorder(BorderSide(Color(0xff000000), 0.0, BorderStyle.none), BorderRadius.zero)', + 'labelStyle: TextStyle(inherit: true, size: 10.0)', + 'secondaryLabelStyle: TextStyle(inherit: true, size: 20.0)', + 'brightness: dark', + 'elevation: 5.0', + 'pressElevation: 6.0', + ]); + }); + + testWidgets('Chip uses ThemeData chip theme', (WidgetTester tester) async { + const ChipThemeData chipTheme = ChipThemeData( + backgroundColor: Color(0xff112233), + elevation: 4, + padding: EdgeInsets.all(50), + labelPadding: EdgeInsets.all(25), + shape: RoundedRectangleBorder(), + labelStyle: TextStyle(fontSize: 32), + ); + + await tester.pumpWidget( + MaterialApp( + theme: ThemeData.light().copyWith( + chipTheme: chipTheme, + ), + home: Directionality( + textDirection: TextDirection.ltr, + child: Material( + child: Center( + child: RawChip( + label: const SizedBox(width: 100, height: 100), + onSelected: (bool newValue) { }, + ), + ), + ), + ), + ), + ); + + final RenderBox materialBox = getMaterialBox(tester); + expect(materialBox, paints..path(color: chipTheme.backgroundColor)); + expect(getMaterial(tester).elevation, chipTheme.elevation); + expect(tester.getSize(find.byType(RawChip)), const Size(250, 250)); // label + padding + labelPadding + expect(getMaterial(tester).shape, chipTheme.shape); + expect(getLabelStyle(tester).style.fontSize, 32); + }); + + testWidgets('Chip uses ChipTheme', (WidgetTester tester) async { + const ChipThemeData chipTheme = ChipThemeData( + backgroundColor: Color(0xff112233), + elevation: 4, + padding: EdgeInsets.all(50), + labelPadding: EdgeInsets.all(25), + labelStyle: TextStyle(fontSize: 32), + shape: RoundedRectangleBorder(), + ); + + const ChipThemeData shadowedChipTheme = ChipThemeData( + backgroundColor: Color(0xff332211), + elevation: 3, + padding: EdgeInsets.all(5), + labelPadding: EdgeInsets.all(10), + labelStyle: TextStyle(fontSize: 64), + shape: CircleBorder(), + ); + + await tester.pumpWidget( + MaterialApp( + theme: ThemeData.light().copyWith( + chipTheme: shadowedChipTheme, + ), + home: ChipTheme( + data: chipTheme, + child: Builder( + builder: (BuildContext context) { + return Directionality( + textDirection: TextDirection.ltr, + child: Material( + child: Center( + child: RawChip( + label: const SizedBox(width: 100, height: 100), + onSelected: (bool newValue) { }, + ), + ), + ), + ); + }, + ), + ), + ), + ); + + final RenderBox materialBox = getMaterialBox(tester); + expect(materialBox, paints..path(color: chipTheme.backgroundColor)); + expect(tester.getSize(find.byType(RawChip)), const Size(250, 250)); // label + padding + labelPadding + expect(getMaterial(tester).elevation, chipTheme.elevation); + expect(getMaterial(tester).shape, chipTheme.shape); + expect(getLabelStyle(tester).style.fontSize, 32); + }); + + testWidgets('Chip uses constructor parameters', (WidgetTester tester) async { + const ChipThemeData shadowedChipTheme = ChipThemeData( + backgroundColor: Color(0xff112233), + elevation: 4, + padding: EdgeInsets.all(5), + labelPadding: EdgeInsets.all(2), + labelStyle: TextStyle(), + shape: RoundedRectangleBorder(), + ); + + const Color backgroundColor = Color(0xff332211); + const double elevation = 3; + const double fontSize = 32; + const OutlinedBorder shape = CircleBorder(); + + await tester.pumpWidget( + MaterialApp( + home: ChipTheme( + data: shadowedChipTheme, + child: Builder( + builder: (BuildContext context) { + return Directionality( + textDirection: TextDirection.ltr, + child: Material( + child: Center( + child: RawChip( + backgroundColor: backgroundColor, + elevation: elevation, + padding: const EdgeInsets.all(50), + labelPadding:const EdgeInsets.all(25), + labelStyle: const TextStyle(fontSize: fontSize), + shape: shape, + label: const SizedBox(width: 100, height: 100), + onSelected: (bool newValue) { }, + ), + ), + ), + ); + }, + ), + ), + ), + ); + + final RenderBox materialBox = getMaterialBox(tester); + expect(materialBox, paints..path(color: backgroundColor)); + expect(tester.getSize(find.byType(RawChip)), const Size(250, 250)); // label + padding + labelPadding + expect(getMaterial(tester).elevation, elevation); + expect(getMaterial(tester).shape, shape); + expect(getLabelStyle(tester).style.fontSize, 32); + }); + + testWidgets('ChipTheme.fromDefaults', (WidgetTester tester) async { + ChipThemeData chipTheme = ChipThemeData.fromDefaults( + brightness: Brightness.light, + secondaryColor: Colors.red, + labelStyle: const TextStyle(), + ); expect(chipTheme.backgroundColor, equals(Colors.black.withAlpha(0x1f))); expect(chipTheme.selectedColor, equals(Colors.black.withAlpha(0x3d))); expect(chipTheme.secondarySelectedColor, equals(Colors.red.withAlpha(0x3d))); expect(chipTheme.deleteIconColor, equals(Colors.black.withAlpha(0xde))); - }); - testWidgets('Chip theme is built by ThemeData with dark mode enabled', (WidgetTester tester) async { - final ThemeData theme = ThemeData( - platform: TargetPlatform.android, + chipTheme = ChipThemeData.fromDefaults( brightness: Brightness.dark, + secondaryColor: Colors.tealAccent[200]!, + labelStyle: const TextStyle(), ); - final ChipThemeData chipTheme = theme.chipTheme; - expect(chipTheme.backgroundColor, equals(Colors.white.withAlpha(0x1f))); expect(chipTheme.selectedColor, equals(Colors.white.withAlpha(0x3d))); expect(chipTheme.secondarySelectedColor, equals(Colors.tealAccent[200]!.withAlpha(0x3d))); expect(chipTheme.deleteIconColor, equals(Colors.white.withAlpha(0xde))); }); - testWidgets('Chip uses ThemeData chip theme if present', (WidgetTester tester) async { - final ThemeData theme = ThemeData( - platform: TargetPlatform.android, - primarySwatch: Colors.red, - backgroundColor: Colors.blue, - ); - final ChipThemeData chipTheme = theme.chipTheme; - - Widget buildChip(ChipThemeData data) { - return MaterialApp( - locale: const Locale('en', 'us'), - home: Directionality( - textDirection: TextDirection.ltr, - child: Material( - child: Center( - child: Theme( - data: theme, - child: RawChip( - onDeleted: () { }, - avatar: const Placeholder(), - deleteIcon: const Placeholder(), - label: const Text('Chip'), - onSelected: (bool newValue) { }, - ), - ), - ), - ), - ), - ); - } - - await tester.pumpWidget(buildChip(chipTheme)); - await tester.pumpAndSettle(); - - final RenderBox materialBox = getMaterialBox(tester); - - expect(materialBox, paints..path(color: chipTheme.backgroundColor)); - }); - - testWidgets('Chip overrides ThemeData theme if ChipTheme present', (WidgetTester tester) async { - final ThemeData theme = ThemeData( - platform: TargetPlatform.android, - primarySwatch: Colors.red, - ); - final ChipThemeData chipTheme = theme.chipTheme; - final ChipThemeData customTheme = chipTheme.copyWith( - backgroundColor: Colors.purple, - deleteIconColor: Colors.purple.withAlpha(0x3d), - elevation: 3.0, - shadowColor: Colors.pink, - ); - const bool value = false; - Widget buildChip(ChipThemeData data) { - return MaterialApp( - home: Directionality( - textDirection: TextDirection.ltr, - child: Material( - child: Center( - child: Theme( - data: theme, - child: ChipTheme( - data: customTheme, - child: RawChip( - onDeleted: () { }, - avatar: const Placeholder(), - deleteIcon: const Placeholder(), - label: const Text('$value'), - onSelected: (bool newValue) { }, - ), - ), - ), - ), - ), - ), - ); - } - - await tester.pumpWidget(buildChip(chipTheme)); - await tester.pumpAndSettle(); - - final RenderBox materialBox = getMaterialBox(tester); - final Material material = getMaterial(tester); - - expect(materialBox, paints..path(color: Color(customTheme.backgroundColor.value))); - expect(material.elevation, customTheme.elevation); - expect(material.shadowColor, customTheme.shadowColor); - }); testWidgets('ChipThemeData generates correct opacities for defaults', (WidgetTester tester) async { const Color customColor1 = Color(0xcafefeed); @@ -183,8 +320,8 @@ void main() { expect(lightTheme.padding, equals(const EdgeInsets.all(4.0))); expect(lightTheme.side, isNull); expect(lightTheme.shape, isNull); - expect(lightTheme.labelStyle.color, equals(Colors.black.withAlpha(0xde))); - expect(lightTheme.secondaryLabelStyle.color, equals(customColor1.withAlpha(0xde))); + expect(lightTheme.labelStyle?.color, equals(Colors.black.withAlpha(0xde))); + expect(lightTheme.secondaryLabelStyle?.color, equals(customColor1.withAlpha(0xde))); expect(lightTheme.brightness, equals(Brightness.light)); final ChipThemeData darkTheme = ChipThemeData.fromDefaults( @@ -202,8 +339,8 @@ void main() { expect(darkTheme.padding, equals(const EdgeInsets.all(4.0))); expect(darkTheme.side, isNull); expect(darkTheme.shape, isNull); - expect(darkTheme.labelStyle.color, equals(Colors.white.withAlpha(0xde))); - expect(darkTheme.secondaryLabelStyle.color, equals(customColor1.withAlpha(0xde))); + expect(darkTheme.labelStyle?.color, equals(Colors.white.withAlpha(0xde))); + expect(darkTheme.secondaryLabelStyle?.color, equals(customColor1.withAlpha(0xde))); expect(darkTheme.brightness, equals(Brightness.dark)); final ChipThemeData customTheme = ChipThemeData.fromDefaults( @@ -212,7 +349,7 @@ void main() { labelStyle: customStyle, ); - expect(customTheme.backgroundColor, equals(customColor1.withAlpha(0x1f))); + //expect(customTheme.backgroundColor, equals(customColor1.withAlpha(0x1f))); expect(customTheme.deleteIconColor, equals(customColor1.withAlpha(0xde))); expect(customTheme.disabledColor, equals(customColor1.withAlpha(0x0c))); expect(customTheme.selectedColor, equals(customColor1.withAlpha(0x3d))); @@ -221,8 +358,8 @@ void main() { expect(customTheme.padding, equals(const EdgeInsets.all(4.0))); expect(customTheme.side, isNull); expect(customTheme.shape, isNull); - expect(customTheme.labelStyle.color, equals(customColor1.withAlpha(0xde))); - expect(customTheme.secondaryLabelStyle.color, equals(customColor2.withAlpha(0xde))); + expect(customTheme.labelStyle?.color, equals(customColor1.withAlpha(0xde))); + expect(customTheme.secondaryLabelStyle?.color, equals(customColor2.withAlpha(0xde))); expect(customTheme.brightness, equals(Brightness.light)); }); @@ -270,8 +407,8 @@ void main() { expect(lerp.padding, equals(const EdgeInsets.all(3.0))); expect(lerp.side!.color, equals(middleGrey)); expect(lerp.shape, isA()); - expect(lerp.labelStyle.color, equals(middleGrey.withAlpha(0xde))); - expect(lerp.secondaryLabelStyle.color, equals(middleGrey.withAlpha(0xde))); + expect(lerp.labelStyle?.color, equals(middleGrey.withAlpha(0xde))); + expect(lerp.secondaryLabelStyle?.color, equals(middleGrey.withAlpha(0xde))); expect(lerp.brightness, equals(Brightness.light)); expect(lerp.elevation, 3.0); expect(lerp.pressElevation, 7.0); @@ -291,8 +428,8 @@ void main() { expect(lerpANull25.padding, equals(const EdgeInsets.all(0.5))); expect(lerpANull25.side!.color, equals(Colors.white.withAlpha(0x3f))); expect(lerpANull25.shape, isA()); - expect(lerpANull25.labelStyle.color, equals(Colors.black.withAlpha(0x38))); - expect(lerpANull25.secondaryLabelStyle.color, equals(Colors.white.withAlpha(0x38))); + expect(lerpANull25.labelStyle?.color, equals(Colors.black.withAlpha(0x38))); + expect(lerpANull25.secondaryLabelStyle?.color, equals(Colors.white.withAlpha(0x38))); expect(lerpANull25.brightness, equals(Brightness.light)); expect(lerpANull25.elevation, 1.25); expect(lerpANull25.pressElevation, 2.5); @@ -310,8 +447,8 @@ void main() { expect(lerpANull75.padding, equals(const EdgeInsets.all(1.5))); expect(lerpANull75.side!.color, equals(Colors.white.withAlpha(0xbf))); expect(lerpANull75.shape, isA()); - expect(lerpANull75.labelStyle.color, equals(Colors.black.withAlpha(0xa7))); - expect(lerpANull75.secondaryLabelStyle.color, equals(Colors.white.withAlpha(0xa7))); + expect(lerpANull75.labelStyle?.color, equals(Colors.black.withAlpha(0xa7))); + expect(lerpANull75.secondaryLabelStyle?.color, equals(Colors.white.withAlpha(0xa7))); expect(lerpANull75.brightness, equals(Brightness.light)); expect(lerpANull75.elevation, 3.75); expect(lerpANull75.pressElevation, 7.5); @@ -329,8 +466,8 @@ void main() { expect(lerpBNull25.padding, equals(const EdgeInsets.all(3.0))); expect(lerpBNull25.side!.color, equals(Colors.black.withAlpha(0x3f))); expect(lerpBNull25.shape, isA()); - expect(lerpBNull25.labelStyle.color, equals(Colors.white.withAlpha(0xa7))); - expect(lerpBNull25.secondaryLabelStyle.color, equals(Colors.black.withAlpha(0xa7))); + expect(lerpBNull25.labelStyle?.color, equals(Colors.white.withAlpha(0xa7))); + expect(lerpBNull25.secondaryLabelStyle?.color, equals(Colors.black.withAlpha(0xa7))); expect(lerpBNull25.brightness, equals(Brightness.dark)); expect(lerpBNull25.elevation, 0.75); expect(lerpBNull25.pressElevation, 3.0); @@ -348,8 +485,8 @@ void main() { expect(lerpBNull75.padding, equals(const EdgeInsets.all(1.0))); expect(lerpBNull75.side!.color, equals(Colors.black.withAlpha(0xbf))); expect(lerpBNull75.shape, isA()); - expect(lerpBNull75.labelStyle.color, equals(Colors.white.withAlpha(0x38))); - expect(lerpBNull75.secondaryLabelStyle.color, equals(Colors.black.withAlpha(0x38))); + expect(lerpBNull75.labelStyle?.color, equals(Colors.white.withAlpha(0x38))); + expect(lerpBNull75.secondaryLabelStyle?.color, equals(Colors.black.withAlpha(0x38))); expect(lerpBNull75.brightness, equals(Brightness.light)); expect(lerpBNull75.elevation, 0.25); expect(lerpBNull75.pressElevation, 1.0); @@ -495,20 +632,22 @@ void main() { BorderSide getBorderSide(Set states) { Color color = defaultColor; - if (states.contains(MaterialState.selected)) color = selectedColor; - return BorderSide(color: color); } + final ChipThemeData chipTheme = ChipThemeData.fromDefaults( + brightness: Brightness.light, + secondaryColor: Colors.blue, + labelStyle: const TextStyle(), + ).copyWith( + side: _MaterialStateBorderSide(getBorderSide), + ); + Widget chipWidget({ bool selected = false }) { return MaterialApp( - theme: ThemeData( - chipTheme: ThemeData.light().chipTheme.copyWith( - side: _MaterialStateBorderSide(getBorderSide), - ), - ), + theme: ThemeData(chipTheme: chipTheme), home: Scaffold( body: ChoiceChip( label: const Text('Chip'), @@ -536,13 +675,18 @@ void main() { return null; } + final ChipThemeData chipTheme = ChipThemeData.fromDefaults( + brightness: Brightness.light, + secondaryColor: Colors.blue, + labelStyle: const TextStyle(), + ).copyWith( + shape: _MaterialStateOutlinedBorder(getShape), + ); + + Widget chipWidget({ bool selected = false }) { return MaterialApp( - theme: ThemeData( - chipTheme: ThemeData.light().chipTheme.copyWith( - shape: _MaterialStateOutlinedBorder(getShape), - ), - ), + theme: ThemeData(chipTheme: chipTheme), home: Scaffold( body: ChoiceChip( label: const Text('Chip'), diff --git a/packages/flutter/test/material/theme_data_test.dart b/packages/flutter/test/material/theme_data_test.dart index e310f2e08a..24dcb9056c 100644 --- a/packages/flutter/test/material/theme_data_test.dart +++ b/packages/flutter/test/material/theme_data_test.dart @@ -51,16 +51,6 @@ void main() { expect(darkTheme.primaryTextTheme.headline6!.color, typography.white.headline6!.color); }); - test('Default chip label style gets a default bodyText1 if textTheme.bodyText1 is null', () { - const TextTheme noBodyText1TextTheme = TextTheme(); - final ThemeData lightTheme = ThemeData(brightness: Brightness.light, textTheme: noBodyText1TextTheme); - final ThemeData darkTheme = ThemeData(brightness: Brightness.dark, textTheme: noBodyText1TextTheme); - final Typography typography = Typography.material2018(platform: lightTheme.platform); - - expect(lightTheme.chipTheme.labelStyle.color, equals(typography.black.bodyText1!.color!.withAlpha(0xde))); - expect(darkTheme.chipTheme.labelStyle.color, equals(typography.white.bodyText1!.color!.withAlpha(0xde))); - }); - test('Default icon theme contrasts with brightness', () { final ThemeData lightTheme = ThemeData(brightness: Brightness.light); final ThemeData darkTheme = ThemeData(brightness: Brightness.dark);