Fix Local SwitchTheme not being inherited by Switch Widget (#97705)

This commit is contained in:
Taha Tesser 2022-02-03 23:45:20 +02:00 committed by GitHub
parent 17a77164d7
commit 3bba8df83b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 62 additions and 14 deletions

View file

@ -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<MaterialState> 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<MaterialState> 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<MaterialState> 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<MaterialState> 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<MaterialState> 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<MouseCursor> effectiveMouseCursor = MaterialStateProperty.resolveWith<MouseCursor>((Set<MaterialState> states) {
return MaterialStateProperty.resolveAs<MouseCursor?>(widget.mouseCursor, states)
?? theme.switchTheme.mouseCursor?.resolve(states)
?? switchTheme.mouseCursor?.resolve(states)
?? MaterialStateProperty.resolveAs<MouseCursor>(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)

View file

@ -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<Color>(globalThemeThumbColor),
trackColor: MaterialStateProperty.all<Color>(globalThemeTrackColor),
),
),
home: Scaffold(
body: SwitchTheme(
data: SwitchThemeData(
thumbColor: MaterialStateProperty.all<Color>(localThemeThumbColor),
trackColor: MaterialStateProperty.all<Color>(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<void> _pointGestureToSwitch(WidgetTester tester) async {