diff --git a/packages/flutter/lib/src/material/switch.dart b/packages/flutter/lib/src/material/switch.dart index 6a71b7f782..904f635503 100644 --- a/packages/flutter/lib/src/material/switch.dart +++ b/packages/flutter/lib/src/material/switch.dart @@ -12,6 +12,7 @@ import 'constants.dart'; import 'debug.dart'; import 'material_state.dart'; import 'shadows.dart'; +import 'switch_theme.dart'; import 'theme.dart'; import 'theme_data.dart'; import 'toggleable.dart'; @@ -397,9 +398,12 @@ class Switch extends StatelessWidget { /// {@macro flutter.widgets.Focus.autofocus} final bool autofocus; - Size _getSwitchSize(ThemeData theme) { + Size _getSwitchSize(BuildContext context) { + final ThemeData theme = Theme.of(context); + final SwitchThemeData switchTheme = SwitchTheme.of(context); + final MaterialTapTargetSize effectiveMaterialTapTargetSize = materialTapTargetSize - ?? theme.switchTheme.materialTapTargetSize + ?? switchTheme.materialTapTargetSize ?? theme.materialTapTargetSize; switch (effectiveMaterialTapTargetSize) { case MaterialTapTargetSize.padded: @@ -410,7 +414,7 @@ class Switch extends StatelessWidget { } Widget _buildCupertinoSwitch(BuildContext context) { - final Size size = _getSwitchSize(Theme.of(context)); + final Size size = _getSwitchSize(context); return Focus( focusNode: focusNode, autofocus: autofocus, @@ -433,7 +437,7 @@ class Switch extends StatelessWidget { return _MaterialSwitch( value: value, onChanged: onChanged, - size: _getSwitchSize(Theme.of(context)), + size: _getSwitchSize(context), activeColor: activeColor, activeTrackColor: activeTrackColor, inactiveThumbColor: inactiveThumbColor, @@ -691,6 +695,7 @@ class _MaterialSwitchState extends State<_MaterialSwitch> with TickerProviderSta } final ThemeData theme = Theme.of(context); + final SwitchThemeData switchTheme = SwitchTheme.of(context); // Colors need to be resolved in selected and non selected states separately // so that they can be lerped between. @@ -698,46 +703,46 @@ class _MaterialSwitchState extends State<_MaterialSwitch> with TickerProviderSta final Set inactiveStates = states..remove(MaterialState.selected); final Color effectiveActiveThumbColor = widget.thumbColor?.resolve(activeStates) ?? _widgetThumbColor.resolve(activeStates) - ?? theme.switchTheme.thumbColor?.resolve(activeStates) + ?? switchTheme.thumbColor?.resolve(activeStates) ?? _defaultThumbColor.resolve(activeStates); final Color effectiveInactiveThumbColor = widget.thumbColor?.resolve(inactiveStates) ?? _widgetThumbColor.resolve(inactiveStates) - ?? theme.switchTheme.thumbColor?.resolve(inactiveStates) + ?? switchTheme.thumbColor?.resolve(inactiveStates) ?? _defaultThumbColor.resolve(inactiveStates); final Color effectiveActiveTrackColor = widget.trackColor?.resolve(activeStates) ?? _widgetTrackColor.resolve(activeStates) - ?? theme.switchTheme.trackColor?.resolve(activeStates) + ?? switchTheme.trackColor?.resolve(activeStates) ?? _defaultTrackColor.resolve(activeStates); final Color effectiveInactiveTrackColor = widget.trackColor?.resolve(inactiveStates) ?? _widgetTrackColor.resolve(inactiveStates) - ?? theme.switchTheme.trackColor?.resolve(inactiveStates) + ?? switchTheme.trackColor?.resolve(inactiveStates) ?? _defaultTrackColor.resolve(inactiveStates); final Set focusedStates = states..add(MaterialState.focused); final Color effectiveFocusOverlayColor = widget.overlayColor?.resolve(focusedStates) ?? widget.focusColor - ?? theme.switchTheme.overlayColor?.resolve(focusedStates) + ?? switchTheme.overlayColor?.resolve(focusedStates) ?? theme.focusColor; final Set hoveredStates = states..add(MaterialState.hovered); final Color effectiveHoverOverlayColor = widget.overlayColor?.resolve(hoveredStates) ?? widget.hoverColor - ?? theme.switchTheme.overlayColor?.resolve(hoveredStates) + ?? switchTheme.overlayColor?.resolve(hoveredStates) ?? theme.hoverColor; final Set activePressedStates = activeStates..add(MaterialState.pressed); final Color effectiveActivePressedOverlayColor = widget.overlayColor?.resolve(activePressedStates) - ?? theme.switchTheme.overlayColor?.resolve(activePressedStates) + ?? switchTheme.overlayColor?.resolve(activePressedStates) ?? effectiveActiveThumbColor.withAlpha(kRadialReactionAlpha); final Set inactivePressedStates = inactiveStates..add(MaterialState.pressed); final Color effectiveInactivePressedOverlayColor = widget.overlayColor?.resolve(inactivePressedStates) - ?? theme.switchTheme.overlayColor?.resolve(inactivePressedStates) + ?? switchTheme.overlayColor?.resolve(inactivePressedStates) ?? effectiveActiveThumbColor.withAlpha(kRadialReactionAlpha); final MaterialStateProperty effectiveMouseCursor = MaterialStateProperty.resolveWith((Set states) { return MaterialStateProperty.resolveAs(widget.mouseCursor, states) - ?? theme.switchTheme.mouseCursor?.resolve(states) + ?? switchTheme.mouseCursor?.resolve(states) ?? MaterialStateProperty.resolveAs(MaterialStateMouseCursor.clickable, states); }); @@ -763,7 +768,7 @@ class _MaterialSwitchState extends State<_MaterialSwitch> with TickerProviderSta ..reactionColor = effectiveActivePressedOverlayColor ..hoverColor = effectiveHoverOverlayColor ..focusColor = effectiveFocusOverlayColor - ..splashRadius = widget.splashRadius ?? theme.switchTheme.splashRadius ?? kRadialReactionRadius + ..splashRadius = widget.splashRadius ?? switchTheme.splashRadius ?? kRadialReactionRadius ..downPosition = downPosition ..isFocused = states.contains(MaterialState.focused) ..isHovered = states.contains(MaterialState.hovered) diff --git a/packages/flutter/test/material/switch_theme_test.dart b/packages/flutter/test/material/switch_theme_test.dart index 7943e222c3..12a28f79f8 100644 --- a/packages/flutter/test/material/switch_theme_test.dart +++ b/packages/flutter/test/material/switch_theme_test.dart @@ -419,6 +419,49 @@ void main() { reason: 'Active pressed Switch should have overlay color: $activePressedOverlayColor', ); }); + + testWidgets('Local SwitchTheme can override global SwitchTheme', (WidgetTester tester) async { + const Color globalThemeThumbColor = Color(0xfffffff1); + const Color globalThemeTrackColor = Color(0xfffffff2); + const Color localThemeThumbColor = Color(0xffff0000); + const Color localThemeTrackColor = Color(0xffff0000); + + Widget buildSwitch({bool selected = false, bool autofocus = false}) { + return MaterialApp( + theme: ThemeData( + switchTheme: SwitchThemeData( + thumbColor: MaterialStateProperty.all(globalThemeThumbColor), + trackColor: MaterialStateProperty.all(globalThemeTrackColor), + ), + ), + home: Scaffold( + body: SwitchTheme( + data: SwitchThemeData( + thumbColor: MaterialStateProperty.all(localThemeThumbColor), + trackColor: MaterialStateProperty.all(localThemeTrackColor), + ), + child: Switch( + value: selected, + onChanged: (bool value) {}, + autofocus: autofocus, + ), + ), + ), + ); + } + + await tester.pumpWidget(buildSwitch(selected: true)); + await tester.pumpAndSettle(); + expect( + _getSwitchMaterial(tester), + paints + ..rrect(color: localThemeTrackColor) + ..circle() + ..circle() + ..circle() + ..circle(color: localThemeThumbColor), + ); + }); } Future _pointGestureToSwitch(WidgetTester tester) async {