Unverified Commit c1c2513a authored by Qun Cheng's avatar Qun Cheng Committed by GitHub

Add `Switch.trackOutlineWidth` property (#125848)

parent 78ed142f
...@@ -126,6 +126,9 @@ class _${blockName}DefaultsM3 extends SwitchThemeData { ...@@ -126,6 +126,9 @@ class _${blockName}DefaultsM3 extends SwitchThemeData {
}); });
} }
@override
MaterialStatePropertyAll<double> get trackOutlineWidth => const MaterialStatePropertyAll<double>(${tokens['md.comp.switch.track.outline.width']});
@override @override
double get splashRadius => ${tokens['md.comp.switch.state-layer.size']} / 2; double get splashRadius => ${tokens['md.comp.switch.state-layer.size']} / 2;
} }
......
...@@ -106,6 +106,7 @@ class Switch extends StatelessWidget { ...@@ -106,6 +106,7 @@ class Switch extends StatelessWidget {
this.thumbColor, this.thumbColor,
this.trackColor, this.trackColor,
this.trackOutlineColor, this.trackOutlineColor,
this.trackOutlineWidth,
this.thumbIcon, this.thumbIcon,
this.materialTapTargetSize, this.materialTapTargetSize,
this.dragStartBehavior = DragStartBehavior.start, this.dragStartBehavior = DragStartBehavior.start,
...@@ -132,7 +133,7 @@ class Switch extends StatelessWidget { ...@@ -132,7 +133,7 @@ class Switch extends StatelessWidget {
/// design [Switch]. /// design [Switch].
/// ///
/// If a [CupertinoSwitch] is created, the following parameters are ignored: /// If a [CupertinoSwitch] is created, the following parameters are ignored:
/// [activeTrackColor], [inactiveThumbColor], [inactiveTrackColor], /// [activeTrackColor], [inactiveThumbColor], [inactiveTrackColor], [trackOutlineWidth]
/// [activeThumbImage], [onActiveThumbImageError], [inactiveThumbImage], /// [activeThumbImage], [onActiveThumbImageError], [inactiveThumbImage],
/// [onInactiveThumbImageError], [materialTapTargetSize]. /// [onInactiveThumbImageError], [materialTapTargetSize].
/// ///
...@@ -153,6 +154,7 @@ class Switch extends StatelessWidget { ...@@ -153,6 +154,7 @@ class Switch extends StatelessWidget {
this.thumbColor, this.thumbColor,
this.trackColor, this.trackColor,
this.trackOutlineColor, this.trackOutlineColor,
this.trackOutlineWidth,
this.thumbIcon, this.thumbIcon,
this.dragStartBehavior = DragStartBehavior.start, this.dragStartBehavior = DragStartBehavior.start,
this.mouseCursor, this.mouseCursor,
...@@ -286,7 +288,7 @@ class Switch extends StatelessWidget { ...@@ -286,7 +288,7 @@ class Switch extends StatelessWidget {
/// ```dart /// ```dart
/// Switch( /// Switch(
/// value: true, /// value: true,
/// onChanged: (_) => true, /// onChanged: (bool value) { },
/// thumbColor: MaterialStateProperty.resolveWith<Color>((Set<MaterialState> states) { /// thumbColor: MaterialStateProperty.resolveWith<Color>((Set<MaterialState> states) {
/// if (states.contains(MaterialState.disabled)) { /// if (states.contains(MaterialState.disabled)) {
/// return Colors.orange.withOpacity(.48); /// return Colors.orange.withOpacity(.48);
...@@ -327,7 +329,7 @@ class Switch extends StatelessWidget { ...@@ -327,7 +329,7 @@ class Switch extends StatelessWidget {
/// ```dart /// ```dart
/// Switch( /// Switch(
/// value: true, /// value: true,
/// onChanged: (_) => true, /// onChanged: (bool value) { },
/// thumbColor: MaterialStateProperty.resolveWith<Color>((Set<MaterialState> states) { /// thumbColor: MaterialStateProperty.resolveWith<Color>((Set<MaterialState> states) {
/// if (states.contains(MaterialState.disabled)) { /// if (states.contains(MaterialState.disabled)) {
/// return Colors.orange.withOpacity(.48); /// return Colors.orange.withOpacity(.48);
...@@ -368,7 +370,7 @@ class Switch extends StatelessWidget { ...@@ -368,7 +370,7 @@ class Switch extends StatelessWidget {
/// ```dart /// ```dart
/// Switch( /// Switch(
/// value: true, /// value: true,
/// onChanged: (_) => true, /// onChanged: (bool value) { },
/// trackOutlineColor: MaterialStateProperty.resolveWith<Color?>((Set<MaterialState> states) { /// trackOutlineColor: MaterialStateProperty.resolveWith<Color?>((Set<MaterialState> states) {
/// if (states.contains(MaterialState.disabled)) { /// if (states.contains(MaterialState.disabled)) {
/// return Colors.orange.withOpacity(.48); /// return Colors.orange.withOpacity(.48);
...@@ -385,6 +387,38 @@ class Switch extends StatelessWidget { ...@@ -385,6 +387,38 @@ class Switch extends StatelessWidget {
/// the [Switch] track has no outline by default. /// the [Switch] track has no outline by default.
final MaterialStateProperty<Color?>? trackOutlineColor; final MaterialStateProperty<Color?>? trackOutlineColor;
/// {@template flutter.material.switch.trackOutlineWidth}
/// The outline width of this [Switch]'s track.
///
/// Resolved in the following states:
/// * [MaterialState.selected].
/// * [MaterialState.hovered].
/// * [MaterialState.focused].
/// * [MaterialState.disabled].
///
/// {@tool snippet}
/// This example resolves the [trackOutlineWidth] based on the current
/// [MaterialState] of the [Switch], providing a different outline width when it is
/// [MaterialState.disabled].
///
/// ```dart
/// Switch(
/// value: true,
/// onChanged: (bool value) { },
/// trackOutlineWidth: MaterialStateProperty.resolveWith<double?>((Set<MaterialState> states) {
/// if (states.contains(MaterialState.disabled)) {
/// return 5.0;
/// }
/// return null; // Use the default width.
/// }),
/// )
/// ```
/// {@end-tool}
/// {@endtemplate}
///
/// Defaults to 2.0.
final MaterialStateProperty<double?>? trackOutlineWidth;
/// {@template flutter.material.switch.thumbIcon} /// {@template flutter.material.switch.thumbIcon}
/// The icon to use on the thumb of this switch /// The icon to use on the thumb of this switch
/// ///
...@@ -402,7 +436,7 @@ class Switch extends StatelessWidget { ...@@ -402,7 +436,7 @@ class Switch extends StatelessWidget {
/// ```dart /// ```dart
/// Switch( /// Switch(
/// value: true, /// value: true,
/// onChanged: (_) => true, /// onChanged: (bool value) { },
/// thumbIcon: MaterialStateProperty.resolveWith<Icon?>((Set<MaterialState> states) { /// thumbIcon: MaterialStateProperty.resolveWith<Icon?>((Set<MaterialState> states) {
/// if (states.contains(MaterialState.disabled)) { /// if (states.contains(MaterialState.disabled)) {
/// return const Icon(Icons.close); /// return const Icon(Icons.close);
...@@ -572,6 +606,7 @@ class Switch extends StatelessWidget { ...@@ -572,6 +606,7 @@ class Switch extends StatelessWidget {
thumbColor: thumbColor, thumbColor: thumbColor,
trackColor: trackColor, trackColor: trackColor,
trackOutlineColor: trackOutlineColor, trackOutlineColor: trackOutlineColor,
trackOutlineWidth: trackOutlineWidth,
thumbIcon: thumbIcon, thumbIcon: thumbIcon,
materialTapTargetSize: materialTapTargetSize, materialTapTargetSize: materialTapTargetSize,
dragStartBehavior: dragStartBehavior, dragStartBehavior: dragStartBehavior,
...@@ -632,6 +667,7 @@ class _MaterialSwitch extends StatefulWidget { ...@@ -632,6 +667,7 @@ class _MaterialSwitch extends StatefulWidget {
this.thumbColor, this.thumbColor,
this.trackColor, this.trackColor,
this.trackOutlineColor, this.trackOutlineColor,
this.trackOutlineWidth,
this.thumbIcon, this.thumbIcon,
this.materialTapTargetSize, this.materialTapTargetSize,
this.dragStartBehavior = DragStartBehavior.start, this.dragStartBehavior = DragStartBehavior.start,
...@@ -659,6 +695,7 @@ class _MaterialSwitch extends StatefulWidget { ...@@ -659,6 +695,7 @@ class _MaterialSwitch extends StatefulWidget {
final MaterialStateProperty<Color?>? thumbColor; final MaterialStateProperty<Color?>? thumbColor;
final MaterialStateProperty<Color?>? trackColor; final MaterialStateProperty<Color?>? trackColor;
final MaterialStateProperty<Color?>? trackOutlineColor; final MaterialStateProperty<Color?>? trackOutlineColor;
final MaterialStateProperty<double?>? trackOutlineWidth;
final MaterialStateProperty<Icon?>? thumbIcon; final MaterialStateProperty<Icon?>? thumbIcon;
final MaterialTapTargetSize? materialTapTargetSize; final MaterialTapTargetSize? materialTapTargetSize;
final DragStartBehavior dragStartBehavior; final DragStartBehavior dragStartBehavior;
...@@ -821,6 +858,9 @@ class _MaterialSwitchState extends State<_MaterialSwitch> with TickerProviderSta ...@@ -821,6 +858,9 @@ class _MaterialSwitchState extends State<_MaterialSwitch> with TickerProviderSta
final Color effectiveActiveTrackOutlineColor = widget.trackOutlineColor?.resolve(activeStates) final Color effectiveActiveTrackOutlineColor = widget.trackOutlineColor?.resolve(activeStates)
?? switchTheme.trackOutlineColor?.resolve(activeStates) ?? switchTheme.trackOutlineColor?.resolve(activeStates)
?? Colors.transparent; ?? Colors.transparent;
final double? effectiveActiveTrackOutlineWidth = widget.trackOutlineWidth?.resolve(activeStates)
?? switchTheme.trackOutlineWidth?.resolve(activeStates)
?? defaults.trackOutlineWidth?.resolve(activeStates);
final Color effectiveInactiveTrackColor = widget.trackColor?.resolve(inactiveStates) final Color effectiveInactiveTrackColor = widget.trackColor?.resolve(inactiveStates)
?? _widgetTrackColor.resolve(inactiveStates) ?? _widgetTrackColor.resolve(inactiveStates)
...@@ -829,6 +869,9 @@ class _MaterialSwitchState extends State<_MaterialSwitch> with TickerProviderSta ...@@ -829,6 +869,9 @@ class _MaterialSwitchState extends State<_MaterialSwitch> with TickerProviderSta
final Color? effectiveInactiveTrackOutlineColor = widget.trackOutlineColor?.resolve(inactiveStates) final Color? effectiveInactiveTrackOutlineColor = widget.trackOutlineColor?.resolve(inactiveStates)
?? switchTheme.trackOutlineColor?.resolve(inactiveStates) ?? switchTheme.trackOutlineColor?.resolve(inactiveStates)
?? defaults.trackOutlineColor?.resolve(inactiveStates); ?? defaults.trackOutlineColor?.resolve(inactiveStates);
final double? effectiveInactiveTrackOutlineWidth = widget.trackOutlineWidth?.resolve(inactiveStates)
?? switchTheme.trackOutlineWidth?.resolve(inactiveStates)
?? defaults.trackOutlineWidth?.resolve(inactiveStates);
final Icon? effectiveActiveIcon = widget.thumbIcon?.resolve(activeStates) final Icon? effectiveActiveIcon = widget.thumbIcon?.resolve(activeStates)
?? switchTheme.thumbIcon?.resolve(activeStates); ?? switchTheme.thumbIcon?.resolve(activeStates);
...@@ -918,8 +961,10 @@ class _MaterialSwitchState extends State<_MaterialSwitch> with TickerProviderSta ...@@ -918,8 +961,10 @@ class _MaterialSwitchState extends State<_MaterialSwitch> with TickerProviderSta
..onInactiveThumbImageError = widget.onInactiveThumbImageError ..onInactiveThumbImageError = widget.onInactiveThumbImageError
..activeTrackColor = effectiveActiveTrackColor ..activeTrackColor = effectiveActiveTrackColor
..activeTrackOutlineColor = effectiveActiveTrackOutlineColor ..activeTrackOutlineColor = effectiveActiveTrackOutlineColor
..activeTrackOutlineWidth = effectiveActiveTrackOutlineWidth
..inactiveTrackColor = effectiveInactiveTrackColor ..inactiveTrackColor = effectiveInactiveTrackColor
..inactiveTrackOutlineColor = effectiveInactiveTrackOutlineColor ..inactiveTrackOutlineColor = effectiveInactiveTrackOutlineColor
..inactiveTrackOutlineWidth = effectiveInactiveTrackOutlineWidth
..configuration = createLocalImageConfiguration(context) ..configuration = createLocalImageConfiguration(context)
..isInteractive = isInteractive ..isInteractive = isInteractive
..trackInnerLength = _trackInnerLength ..trackInnerLength = _trackInnerLength
...@@ -1169,6 +1214,26 @@ class _SwitchPainter extends ToggleablePainter { ...@@ -1169,6 +1214,26 @@ class _SwitchPainter extends ToggleablePainter {
notifyListeners(); notifyListeners();
} }
double? get activeTrackOutlineWidth => _activeTrackOutlineWidth;
double? _activeTrackOutlineWidth;
set activeTrackOutlineWidth(double? value) {
if (value == _activeTrackOutlineWidth) {
return;
}
_activeTrackOutlineWidth = value;
notifyListeners();
}
double? get inactiveTrackOutlineWidth => _inactiveTrackOutlineWidth;
double? _inactiveTrackOutlineWidth;
set inactiveTrackOutlineWidth(double? value) {
if (value == _inactiveTrackOutlineWidth) {
return;
}
_inactiveTrackOutlineWidth = value;
notifyListeners();
}
Color get inactiveTrackColor => _inactiveTrackColor!; Color get inactiveTrackColor => _inactiveTrackColor!;
Color? _inactiveTrackColor; Color? _inactiveTrackColor;
set inactiveTrackColor(Color value) { set inactiveTrackColor(Color value) {
...@@ -1366,6 +1431,7 @@ class _SwitchPainter extends ToggleablePainter { ...@@ -1366,6 +1431,7 @@ class _SwitchPainter extends ToggleablePainter {
final Color trackColor = Color.lerp(inactiveTrackColor, activeTrackColor, colorValue)!; final Color trackColor = Color.lerp(inactiveTrackColor, activeTrackColor, colorValue)!;
final Color? trackOutlineColor = inactiveTrackOutlineColor == null ? null final Color? trackOutlineColor = inactiveTrackOutlineColor == null ? null
: Color.lerp(inactiveTrackOutlineColor, activeTrackOutlineColor, colorValue); : Color.lerp(inactiveTrackOutlineColor, activeTrackOutlineColor, colorValue);
final double? trackOutlineWidth = lerpDouble(inactiveTrackOutlineWidth, activeTrackOutlineWidth, colorValue);
Color lerpedThumbColor; Color lerpedThumbColor;
if (!reaction.isDismissed) { if (!reaction.isDismissed) {
lerpedThumbColor = Color.lerp(inactivePressedColor, activePressedColor, colorValue)!; lerpedThumbColor = Color.lerp(inactivePressedColor, activePressedColor, colorValue)!;
...@@ -1395,7 +1461,7 @@ class _SwitchPainter extends ToggleablePainter { ...@@ -1395,7 +1461,7 @@ class _SwitchPainter extends ToggleablePainter {
final Offset thumbPaintOffset = _computeThumbPaintOffset(trackPaintOffset, thumbSize, visualPosition); final Offset thumbPaintOffset = _computeThumbPaintOffset(trackPaintOffset, thumbSize, visualPosition);
final Offset radialReactionOrigin = Offset(thumbPaintOffset.dx + thumbSize.height / 2, size.height / 2); final Offset radialReactionOrigin = Offset(thumbPaintOffset.dx + thumbSize.height / 2, size.height / 2);
_paintTrackWith(canvas, paint, trackPaintOffset, trackOutlineColor); _paintTrackWith(canvas, paint, trackPaintOffset, trackOutlineColor, trackOutlineWidth);
paintRadialReaction(canvas: canvas, origin: radialReactionOrigin); paintRadialReaction(canvas: canvas, origin: radialReactionOrigin);
_paintThumbWith( _paintThumbWith(
thumbPaintOffset, thumbPaintOffset,
...@@ -1433,7 +1499,7 @@ class _SwitchPainter extends ToggleablePainter { ...@@ -1433,7 +1499,7 @@ class _SwitchPainter extends ToggleablePainter {
return Offset(thumbHorizontalOffset, thumbVerticalOffset); return Offset(thumbHorizontalOffset, thumbVerticalOffset);
} }
void _paintTrackWith(Canvas canvas, Paint paint, Offset trackPaintOffset, Color? trackOutlineColor) { void _paintTrackWith(Canvas canvas, Paint paint, Offset trackPaintOffset, Color? trackOutlineColor, double? trackOutlineWidth) {
final Rect trackRect = Rect.fromLTWH( final Rect trackRect = Rect.fromLTWH(
trackPaintOffset.dx, trackPaintOffset.dx,
trackPaintOffset.dy, trackPaintOffset.dy,
...@@ -1462,7 +1528,7 @@ class _SwitchPainter extends ToggleablePainter { ...@@ -1462,7 +1528,7 @@ class _SwitchPainter extends ToggleablePainter {
); );
final Paint outlinePaint = Paint() final Paint outlinePaint = Paint()
..style = PaintingStyle.stroke ..style = PaintingStyle.stroke
..strokeWidth = 2 ..strokeWidth = trackOutlineWidth ?? 2.0
..color = trackOutlineColor; ..color = trackOutlineColor;
canvas.drawRRect(outlineTrackRRect, outlinePaint); canvas.drawRRect(outlineTrackRRect, outlinePaint);
} }
...@@ -1808,6 +1874,9 @@ class _SwitchDefaultsM3 extends SwitchThemeData { ...@@ -1808,6 +1874,9 @@ class _SwitchDefaultsM3 extends SwitchThemeData {
}); });
} }
@override
MaterialStatePropertyAll<double> get trackOutlineWidth => const MaterialStatePropertyAll<double>(2.0);
@override @override
double get splashRadius => 40.0 / 2; double get splashRadius => 40.0 / 2;
} }
......
...@@ -40,6 +40,7 @@ class SwitchThemeData with Diagnosticable { ...@@ -40,6 +40,7 @@ class SwitchThemeData with Diagnosticable {
this.thumbColor, this.thumbColor,
this.trackColor, this.trackColor,
this.trackOutlineColor, this.trackOutlineColor,
this.trackOutlineWidth,
this.materialTapTargetSize, this.materialTapTargetSize,
this.mouseCursor, this.mouseCursor,
this.overlayColor, this.overlayColor,
...@@ -62,6 +63,11 @@ class SwitchThemeData with Diagnosticable { ...@@ -62,6 +63,11 @@ class SwitchThemeData with Diagnosticable {
/// If specified, overrides the default value of [Switch.trackOutlineColor]. /// If specified, overrides the default value of [Switch.trackOutlineColor].
final MaterialStateProperty<Color?>? trackOutlineColor; final MaterialStateProperty<Color?>? trackOutlineColor;
/// {@macro flutter.material.switch.trackOutlineWidth}
///
/// If specified, overrides the default value of [Switch.trackOutlineWidth].
final MaterialStateProperty<double?>? trackOutlineWidth;
/// {@macro flutter.material.switch.materialTapTargetSize} /// {@macro flutter.material.switch.materialTapTargetSize}
/// ///
/// If specified, overrides the default value of /// If specified, overrides the default value of
...@@ -94,6 +100,7 @@ class SwitchThemeData with Diagnosticable { ...@@ -94,6 +100,7 @@ class SwitchThemeData with Diagnosticable {
MaterialStateProperty<Color?>? thumbColor, MaterialStateProperty<Color?>? thumbColor,
MaterialStateProperty<Color?>? trackColor, MaterialStateProperty<Color?>? trackColor,
MaterialStateProperty<Color?>? trackOutlineColor, MaterialStateProperty<Color?>? trackOutlineColor,
MaterialStateProperty<double?>? trackOutlineWidth,
MaterialTapTargetSize? materialTapTargetSize, MaterialTapTargetSize? materialTapTargetSize,
MaterialStateProperty<MouseCursor?>? mouseCursor, MaterialStateProperty<MouseCursor?>? mouseCursor,
MaterialStateProperty<Color?>? overlayColor, MaterialStateProperty<Color?>? overlayColor,
...@@ -104,6 +111,7 @@ class SwitchThemeData with Diagnosticable { ...@@ -104,6 +111,7 @@ class SwitchThemeData with Diagnosticable {
thumbColor: thumbColor ?? this.thumbColor, thumbColor: thumbColor ?? this.thumbColor,
trackColor: trackColor ?? this.trackColor, trackColor: trackColor ?? this.trackColor,
trackOutlineColor: trackOutlineColor ?? this.trackOutlineColor, trackOutlineColor: trackOutlineColor ?? this.trackOutlineColor,
trackOutlineWidth: trackOutlineWidth ?? this.trackOutlineWidth,
materialTapTargetSize: materialTapTargetSize ?? this.materialTapTargetSize, materialTapTargetSize: materialTapTargetSize ?? this.materialTapTargetSize,
mouseCursor: mouseCursor ?? this.mouseCursor, mouseCursor: mouseCursor ?? this.mouseCursor,
overlayColor: overlayColor ?? this.overlayColor, overlayColor: overlayColor ?? this.overlayColor,
...@@ -123,6 +131,7 @@ class SwitchThemeData with Diagnosticable { ...@@ -123,6 +131,7 @@ class SwitchThemeData with Diagnosticable {
thumbColor: MaterialStateProperty.lerp<Color?>(a?.thumbColor, b?.thumbColor, t, Color.lerp), thumbColor: MaterialStateProperty.lerp<Color?>(a?.thumbColor, b?.thumbColor, t, Color.lerp),
trackColor: MaterialStateProperty.lerp<Color?>(a?.trackColor, b?.trackColor, t, Color.lerp), trackColor: MaterialStateProperty.lerp<Color?>(a?.trackColor, b?.trackColor, t, Color.lerp),
trackOutlineColor: MaterialStateProperty.lerp<Color?>(a?.trackOutlineColor, b?.trackOutlineColor, t, Color.lerp), trackOutlineColor: MaterialStateProperty.lerp<Color?>(a?.trackOutlineColor, b?.trackOutlineColor, t, Color.lerp),
trackOutlineWidth: MaterialStateProperty.lerp<double?>(a?.trackOutlineWidth, b?.trackOutlineWidth, t, lerpDouble),
materialTapTargetSize: t < 0.5 ? a?.materialTapTargetSize : b?.materialTapTargetSize, materialTapTargetSize: t < 0.5 ? a?.materialTapTargetSize : b?.materialTapTargetSize,
mouseCursor: t < 0.5 ? a?.mouseCursor : b?.mouseCursor, mouseCursor: t < 0.5 ? a?.mouseCursor : b?.mouseCursor,
overlayColor: MaterialStateProperty.lerp<Color?>(a?.overlayColor, b?.overlayColor, t, Color.lerp), overlayColor: MaterialStateProperty.lerp<Color?>(a?.overlayColor, b?.overlayColor, t, Color.lerp),
...@@ -136,6 +145,7 @@ class SwitchThemeData with Diagnosticable { ...@@ -136,6 +145,7 @@ class SwitchThemeData with Diagnosticable {
thumbColor, thumbColor,
trackColor, trackColor,
trackOutlineColor, trackOutlineColor,
trackOutlineWidth,
materialTapTargetSize, materialTapTargetSize,
mouseCursor, mouseCursor,
overlayColor, overlayColor,
...@@ -155,6 +165,7 @@ class SwitchThemeData with Diagnosticable { ...@@ -155,6 +165,7 @@ class SwitchThemeData with Diagnosticable {
&& other.thumbColor == thumbColor && other.thumbColor == thumbColor
&& other.trackColor == trackColor && other.trackColor == trackColor
&& other.trackOutlineColor == trackOutlineColor && other.trackOutlineColor == trackOutlineColor
&& other.trackOutlineWidth == trackOutlineWidth
&& other.materialTapTargetSize == materialTapTargetSize && other.materialTapTargetSize == materialTapTargetSize
&& other.mouseCursor == mouseCursor && other.mouseCursor == mouseCursor
&& other.overlayColor == overlayColor && other.overlayColor == overlayColor
...@@ -168,6 +179,7 @@ class SwitchThemeData with Diagnosticable { ...@@ -168,6 +179,7 @@ class SwitchThemeData with Diagnosticable {
properties.add(DiagnosticsProperty<MaterialStateProperty<Color?>>('thumbColor', thumbColor, defaultValue: null)); properties.add(DiagnosticsProperty<MaterialStateProperty<Color?>>('thumbColor', thumbColor, defaultValue: null));
properties.add(DiagnosticsProperty<MaterialStateProperty<Color?>>('trackColor', trackColor, defaultValue: null)); properties.add(DiagnosticsProperty<MaterialStateProperty<Color?>>('trackColor', trackColor, defaultValue: null));
properties.add(DiagnosticsProperty<MaterialStateProperty<Color?>>('trackOutlineColor', trackOutlineColor, defaultValue: null)); properties.add(DiagnosticsProperty<MaterialStateProperty<Color?>>('trackOutlineColor', trackOutlineColor, defaultValue: null));
properties.add(DiagnosticsProperty<MaterialStateProperty<double?>>('trackOutlineWidth', trackOutlineWidth, defaultValue: null));
properties.add(DiagnosticsProperty<MaterialTapTargetSize>('materialTapTargetSize', materialTapTargetSize, defaultValue: null)); properties.add(DiagnosticsProperty<MaterialTapTargetSize>('materialTapTargetSize', materialTapTargetSize, defaultValue: null));
properties.add(DiagnosticsProperty<MaterialStateProperty<MouseCursor?>>('mouseCursor', mouseCursor, defaultValue: null)); properties.add(DiagnosticsProperty<MaterialStateProperty<MouseCursor?>>('mouseCursor', mouseCursor, defaultValue: null));
properties.add(DiagnosticsProperty<MaterialStateProperty<Color?>>('overlayColor', overlayColor, defaultValue: null)); properties.add(DiagnosticsProperty<MaterialStateProperty<Color?>>('overlayColor', overlayColor, defaultValue: null));
......
...@@ -2967,6 +2967,141 @@ void main() { ...@@ -2967,6 +2967,141 @@ void main() {
); );
}); });
testWidgets('Track outline width resolves in active/enabled states', (WidgetTester tester) async {
const double activeEnabledTrackOutlineWidth = 1.0;
const double activeDisabledTrackOutlineWidth = 2.0;
const double inactiveEnabledTrackOutlineWidth = 3.0;
const double inactiveDisabledTrackOutlineWidth = 4.0;
double getTrackOutlineWidth(Set<MaterialState> states) {
if (states.contains(MaterialState.disabled)) {
if (states.contains(MaterialState.selected)) {
return activeDisabledTrackOutlineWidth;
}
return inactiveDisabledTrackOutlineWidth;
}
if (states.contains(MaterialState.selected)) {
return activeEnabledTrackOutlineWidth;
}
return inactiveEnabledTrackOutlineWidth;
}
final MaterialStateProperty<double> trackOutlineWidth = MaterialStateProperty.resolveWith(getTrackOutlineWidth);
Widget buildSwitch({required bool enabled, required bool active}) {
return MaterialApp(
theme: ThemeData(useMaterial3: true),
home: Material(
child: Center(
child: Switch(
trackOutlineWidth: trackOutlineWidth,
value: active,
onChanged: enabled ? (_) { } : null,
),
),
),
);
}
await tester.pumpWidget(buildSwitch(enabled: false, active: false));
expect(
Material.of(tester.element(find.byType(Switch))),
paints..rrect(style: PaintingStyle.fill)
..rrect(strokeWidth: inactiveDisabledTrackOutlineWidth, style: PaintingStyle.stroke),
reason: 'Inactive disabled switch track outline width should be 4.0',
);
await tester.pumpWidget(buildSwitch(enabled: false, active: true));
await tester.pumpAndSettle();
expect(
Material.of(tester.element(find.byType(Switch))),
paints..rrect(style: PaintingStyle.fill)
..rrect(strokeWidth: activeDisabledTrackOutlineWidth, style: PaintingStyle.stroke),
reason: 'Active disabled switch track outline width should be 2.0',
);
await tester.pumpWidget(buildSwitch(enabled: true, active: false));
await tester.pumpAndSettle();
expect(
Material.of(tester.element(find.byType(Switch))),
paints..rrect(style: PaintingStyle.fill)
..rrect(strokeWidth: inactiveEnabledTrackOutlineWidth, style: PaintingStyle.stroke),
reason: 'Inactive enabled switch track outline width should be 3.0',
);
await tester.pumpWidget(buildSwitch(enabled: true, active: true));
await tester.pumpAndSettle();
expect(
Material.of(tester.element(find.byType(Switch))),
paints..rrect(style: PaintingStyle.fill)
..rrect(strokeWidth: activeEnabledTrackOutlineWidth, style: PaintingStyle.stroke),
reason: 'Active enabled switch track outline width should be 1.0',
);
});
testWidgets('Switch track outline width resolves in hovered/focused states', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode(debugLabel: 'Switch');
tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
const double hoveredTrackOutlineWidth = 4.0;
const double focusedTrackOutlineWidth = 6.0;
double getTrackOutlineWidth(Set<MaterialState> states) {
if (states.contains(MaterialState.hovered)) {
return hoveredTrackOutlineWidth;
}
if (states.contains(MaterialState.focused)) {
return focusedTrackOutlineWidth;
}
return 8.0;
}
final MaterialStateProperty<double> trackOutlineWidth = MaterialStateProperty.resolveWith(getTrackOutlineWidth);
Widget buildSwitch() {
return MaterialApp(
theme: ThemeData(useMaterial3: true),
home: Material(
child: Center(
child: Switch(
focusNode: focusNode,
autofocus: true,
value: true,
trackOutlineWidth: trackOutlineWidth,
onChanged: (_) { },
),
),
),
);
}
await tester.pumpWidget(buildSwitch());
await tester.pumpAndSettle();
expect(focusNode.hasPrimaryFocus, isTrue);
expect(
Material.of(tester.element(find.byType(Switch))),
paints..rrect(style: PaintingStyle.fill)
..rrect(strokeWidth: focusedTrackOutlineWidth, style: PaintingStyle.stroke),
reason: 'Active enabled switch track outline width should be 6.0',
);
// Start hovering
final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
await gesture.addPointer();
await gesture.moveTo(tester.getCenter(find.byType(Switch)));
await tester.pumpAndSettle();
expect(
Material.of(tester.element(find.byType(Switch))),
paints..rrect(style: PaintingStyle.fill)
..rrect(strokeWidth: hoveredTrackOutlineWidth, style: PaintingStyle.stroke),
reason: 'Active enabled switch track outline width should be 4.0',
);
});
testWidgets('Switch thumb color is blended against surface color - M3', (WidgetTester tester) async { testWidgets('Switch thumb color is blended against surface color - M3', (WidgetTester tester) async {
final Color activeDisabledThumbColor = Colors.blue.withOpacity(.60); final Color activeDisabledThumbColor = Colors.blue.withOpacity(.60);
final ThemeData theme = ThemeData.light(useMaterial3: true); final ThemeData theme = ThemeData.light(useMaterial3: true);
......
...@@ -25,6 +25,7 @@ void main() { ...@@ -25,6 +25,7 @@ void main() {
expect(themeData.thumbColor, null); expect(themeData.thumbColor, null);
expect(themeData.trackColor, null); expect(themeData.trackColor, null);
expect(themeData.trackOutlineColor, null); expect(themeData.trackOutlineColor, null);
expect(themeData.trackOutlineWidth, null);
expect(themeData.mouseCursor, null); expect(themeData.mouseCursor, null);
expect(themeData.materialTapTargetSize, null); expect(themeData.materialTapTargetSize, null);
expect(themeData.overlayColor, null); expect(themeData.overlayColor, null);
...@@ -35,6 +36,7 @@ void main() { ...@@ -35,6 +36,7 @@ void main() {
expect(theme.data.thumbColor, null); expect(theme.data.thumbColor, null);
expect(theme.data.trackColor, null); expect(theme.data.trackColor, null);
expect(theme.data.trackOutlineColor, null); expect(theme.data.trackOutlineColor, null);
expect(theme.data.trackOutlineWidth, null);
expect(theme.data.mouseCursor, null); expect(theme.data.mouseCursor, null);
expect(theme.data.materialTapTargetSize, null); expect(theme.data.materialTapTargetSize, null);
expect(theme.data.overlayColor, null); expect(theme.data.overlayColor, null);
...@@ -60,6 +62,7 @@ void main() { ...@@ -60,6 +62,7 @@ void main() {
thumbColor: MaterialStatePropertyAll<Color>(Color(0xfffffff0)), thumbColor: MaterialStatePropertyAll<Color>(Color(0xfffffff0)),
trackColor: MaterialStatePropertyAll<Color>(Color(0xfffffff1)), trackColor: MaterialStatePropertyAll<Color>(Color(0xfffffff1)),
trackOutlineColor: MaterialStatePropertyAll<Color>(Color(0xfffffff3)), trackOutlineColor: MaterialStatePropertyAll<Color>(Color(0xfffffff3)),
trackOutlineWidth: MaterialStatePropertyAll<double>(6.0),
mouseCursor: MaterialStatePropertyAll<MouseCursor>(SystemMouseCursors.click), mouseCursor: MaterialStatePropertyAll<MouseCursor>(SystemMouseCursors.click),
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
overlayColor: MaterialStatePropertyAll<Color>(Color(0xfffffff2)), overlayColor: MaterialStatePropertyAll<Color>(Color(0xfffffff2)),
...@@ -75,11 +78,12 @@ void main() { ...@@ -75,11 +78,12 @@ void main() {
expect(description[0], 'thumbColor: MaterialStatePropertyAll(Color(0xfffffff0))'); expect(description[0], 'thumbColor: MaterialStatePropertyAll(Color(0xfffffff0))');
expect(description[1], 'trackColor: MaterialStatePropertyAll(Color(0xfffffff1))'); expect(description[1], 'trackColor: MaterialStatePropertyAll(Color(0xfffffff1))');
expect(description[2], 'trackOutlineColor: MaterialStatePropertyAll(Color(0xfffffff3))'); expect(description[2], 'trackOutlineColor: MaterialStatePropertyAll(Color(0xfffffff3))');
expect(description[3], 'materialTapTargetSize: MaterialTapTargetSize.shrinkWrap'); expect(description[3], 'trackOutlineWidth: MaterialStatePropertyAll(6.0)');
expect(description[4], 'mouseCursor: MaterialStatePropertyAll(SystemMouseCursor(click))'); expect(description[4], 'materialTapTargetSize: MaterialTapTargetSize.shrinkWrap');
expect(description[5], 'overlayColor: MaterialStatePropertyAll(Color(0xfffffff2))'); expect(description[5], 'mouseCursor: MaterialStatePropertyAll(SystemMouseCursor(click))');
expect(description[6], 'splashRadius: 1.0'); expect(description[6], 'overlayColor: MaterialStatePropertyAll(Color(0xfffffff2))');
expect(description[7], 'thumbIcon: MaterialStatePropertyAll(Icon(IconData(U+0007B)))'); expect(description[7], 'splashRadius: 1.0');
expect(description[8], 'thumbIcon: MaterialStatePropertyAll(Icon(IconData(U+0007B)))');
}); });
testWidgets('Switch is themeable', (WidgetTester tester) async { testWidgets('Switch is themeable', (WidgetTester tester) async {
...@@ -91,6 +95,8 @@ void main() { ...@@ -91,6 +95,8 @@ void main() {
const Color selectedTrackColor = Color(0xfffffff3); const Color selectedTrackColor = Color(0xfffffff3);
const Color defaultTrackOutlineColor = Color(0xfffffff4); const Color defaultTrackOutlineColor = Color(0xfffffff4);
const Color selectedTrackOutlineColor = Color(0xfffffff5); const Color selectedTrackOutlineColor = Color(0xfffffff5);
const double defaultTrackOutlineWidth = 3.0;
const double selectedTrackOutlineWidth = 6.0;
const MouseCursor mouseCursor = SystemMouseCursors.text; const MouseCursor mouseCursor = SystemMouseCursors.text;
const MaterialTapTargetSize materialTapTargetSize = MaterialTapTargetSize.shrinkWrap; const MaterialTapTargetSize materialTapTargetSize = MaterialTapTargetSize.shrinkWrap;
const Color focusOverlayColor = Color(0xfffffff4); const Color focusOverlayColor = Color(0xfffffff4);
...@@ -119,6 +125,12 @@ void main() { ...@@ -119,6 +125,12 @@ void main() {
} }
return defaultTrackOutlineColor; return defaultTrackOutlineColor;
}), }),
trackOutlineWidth: MaterialStateProperty.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.selected)) {
return selectedTrackOutlineWidth;
}
return defaultTrackOutlineWidth;
}),
mouseCursor: const MaterialStatePropertyAll<MouseCursor>(mouseCursor), mouseCursor: const MaterialStatePropertyAll<MouseCursor>(mouseCursor),
materialTapTargetSize: materialTapTargetSize, materialTapTargetSize: materialTapTargetSize,
overlayColor: MaterialStateProperty.resolveWith((Set<MaterialState> states) { overlayColor: MaterialStateProperty.resolveWith((Set<MaterialState> states) {
...@@ -162,13 +174,13 @@ void main() { ...@@ -162,13 +174,13 @@ void main() {
material3 material3
? (paints ? (paints
..rrect(color: defaultTrackColor) ..rrect(color: defaultTrackColor)
..rrect(color: defaultTrackOutlineColor) ..rrect(color: defaultTrackOutlineColor, strokeWidth: defaultTrackOutlineWidth)
..rrect(color: defaultThumbColor) ..rrect(color: defaultThumbColor)
..paragraph() ..paragraph()
) )
: (paints : (paints
..rrect(color: defaultTrackColor) ..rrect(color: defaultTrackColor)
..rrect(color: defaultTrackOutlineColor) ..rrect(color: defaultTrackOutlineColor, strokeWidth: defaultTrackOutlineWidth)
..rrect() ..rrect()
..rrect() ..rrect()
..rrect() ..rrect()
...@@ -186,11 +198,11 @@ void main() { ...@@ -186,11 +198,11 @@ void main() {
material3 material3
? (paints ? (paints
..rrect(color: selectedTrackColor) ..rrect(color: selectedTrackColor)
..rrect(color: selectedTrackOutlineColor) ..rrect(color: selectedTrackOutlineColor, strokeWidth: selectedTrackOutlineWidth)
..rrect(color: selectedThumbColor)..paragraph()) ..rrect(color: selectedThumbColor)..paragraph())
: (paints : (paints
..rrect(color: selectedTrackColor) ..rrect(color: selectedTrackColor)
..rrect(color: selectedTrackOutlineColor) ..rrect(color: selectedTrackOutlineColor, strokeWidth: selectedTrackOutlineWidth)
..rrect() ..rrect()
..rrect() ..rrect()
..rrect() ..rrect()
...@@ -219,6 +231,8 @@ void main() { ...@@ -219,6 +231,8 @@ void main() {
const Color themeSelectedTrackColor = Color(0xfffffff3); const Color themeSelectedTrackColor = Color(0xfffffff3);
const Color themeDefaultOutlineColor = Color(0xfffffff6); const Color themeDefaultOutlineColor = Color(0xfffffff6);
const Color themeSelectedOutlineColor = Color(0xfffffff7); const Color themeSelectedOutlineColor = Color(0xfffffff7);
const double themeDefaultOutlineWidth = 5.0;
const double themeSelectedOutlineWidth = 7.0;
const MouseCursor themeMouseCursor = SystemMouseCursors.click; const MouseCursor themeMouseCursor = SystemMouseCursors.click;
const MaterialTapTargetSize themeMaterialTapTargetSize = MaterialTapTargetSize.padded; const MaterialTapTargetSize themeMaterialTapTargetSize = MaterialTapTargetSize.padded;
const Color themeFocusOverlayColor = Color(0xfffffff4); const Color themeFocusOverlayColor = Color(0xfffffff4);
...@@ -231,6 +245,8 @@ void main() { ...@@ -231,6 +245,8 @@ void main() {
const Color selectedTrackColor = Color(0xffffff3f); const Color selectedTrackColor = Color(0xffffff3f);
const Color defaultOutlineColor = Color(0xffffff6f); const Color defaultOutlineColor = Color(0xffffff6f);
const Color selectedOutlineColor = Color(0xffffff7f); const Color selectedOutlineColor = Color(0xffffff7f);
const double defaultOutlineWidth = 6.0;
const double selectedOutlineWidth = 8.0;
const MouseCursor mouseCursor = SystemMouseCursors.text; const MouseCursor mouseCursor = SystemMouseCursors.text;
const MaterialTapTargetSize materialTapTargetSize = MaterialTapTargetSize.shrinkWrap; const MaterialTapTargetSize materialTapTargetSize = MaterialTapTargetSize.shrinkWrap;
const Color focusColor = Color(0xffffff4f); const Color focusColor = Color(0xffffff4f);
...@@ -257,6 +273,12 @@ void main() { ...@@ -257,6 +273,12 @@ void main() {
} }
return themeDefaultOutlineColor; return themeDefaultOutlineColor;
}), }),
trackOutlineWidth: MaterialStateProperty.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.selected)) {
return themeSelectedOutlineWidth;
}
return themeDefaultOutlineWidth;
}),
mouseCursor: const MaterialStatePropertyAll<MouseCursor>(themeMouseCursor), mouseCursor: const MaterialStatePropertyAll<MouseCursor>(themeMouseCursor),
materialTapTargetSize: themeMaterialTapTargetSize, materialTapTargetSize: themeMaterialTapTargetSize,
overlayColor: MaterialStateProperty.resolveWith((Set<MaterialState> states) { overlayColor: MaterialStateProperty.resolveWith((Set<MaterialState> states) {
...@@ -305,6 +327,12 @@ void main() { ...@@ -305,6 +327,12 @@ void main() {
} }
return defaultOutlineColor; return defaultOutlineColor;
}), }),
trackOutlineWidth: MaterialStateProperty.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.selected)) {
return selectedOutlineWidth;
}
return defaultOutlineWidth;
}),
mouseCursor: mouseCursor, mouseCursor: mouseCursor,
materialTapTargetSize: materialTapTargetSize, materialTapTargetSize: materialTapTargetSize,
focusColor: focusColor, focusColor: focusColor,
...@@ -329,11 +357,11 @@ void main() { ...@@ -329,11 +357,11 @@ void main() {
material3 material3
? (paints ? (paints
..rrect(color: defaultTrackColor) ..rrect(color: defaultTrackColor)
..rrect(color: defaultOutlineColor) ..rrect(color: defaultOutlineColor, strokeWidth: defaultOutlineWidth)
..rrect(color: defaultThumbColor)..paragraph(offset: const Offset(12, 16))) ..rrect(color: defaultThumbColor)..paragraph(offset: const Offset(12, 16)))
: (paints : (paints
..rrect(color: defaultTrackColor) ..rrect(color: defaultTrackColor)
..rrect(color: defaultOutlineColor) ..rrect(color: defaultOutlineColor, strokeWidth: defaultOutlineWidth)
..rrect() ..rrect()
..rrect() ..rrect()
..rrect() ..rrect()
...@@ -349,11 +377,11 @@ void main() { ...@@ -349,11 +377,11 @@ void main() {
_getSwitchMaterial(tester), _getSwitchMaterial(tester),
material3 material3
? (paints ? (paints
..rrect(color: selectedTrackColor)..rrect(color: selectedOutlineColor) ..rrect(color: selectedTrackColor)..rrect(color: selectedOutlineColor, strokeWidth: selectedOutlineWidth)
..rrect(color: selectedThumbColor)) ..rrect(color: selectedThumbColor))
: (paints : (paints
..rrect(color: selectedTrackColor) ..rrect(color: selectedTrackColor)
..rrect(color: selectedOutlineColor) ..rrect(color: selectedOutlineColor, strokeWidth: selectedOutlineWidth)
..rrect() ..rrect()
..rrect() ..rrect()
..rrect() ..rrect()
...@@ -534,15 +562,18 @@ void main() { ...@@ -534,15 +562,18 @@ void main() {
const Color globalThemeThumbColor = Color(0xfffffff1); const Color globalThemeThumbColor = Color(0xfffffff1);
const Color globalThemeTrackColor = Color(0xfffffff2); const Color globalThemeTrackColor = Color(0xfffffff2);
const Color globalThemeOutlineColor = Color(0xfffffff3); const Color globalThemeOutlineColor = Color(0xfffffff3);
const double globalThemeOutlineWidth = 6.0;
const Color localThemeThumbColor = Color(0xffff0000); const Color localThemeThumbColor = Color(0xffff0000);
const Color localThemeTrackColor = Color(0xffff0000); const Color localThemeTrackColor = Color(0xffff0000);
const Color localThemeOutlineColor = Color(0xffff0000); const Color localThemeOutlineColor = Color(0xffff0000);
const double localThemeOutlineWidth = 4.0;
final ThemeData themeData = ThemeData( final ThemeData themeData = ThemeData(
switchTheme: const SwitchThemeData( switchTheme: const SwitchThemeData(
thumbColor: MaterialStatePropertyAll<Color>(globalThemeThumbColor), thumbColor: MaterialStatePropertyAll<Color>(globalThemeThumbColor),
trackColor: MaterialStatePropertyAll<Color>(globalThemeTrackColor), trackColor: MaterialStatePropertyAll<Color>(globalThemeTrackColor),
trackOutlineColor: MaterialStatePropertyAll<Color>(globalThemeOutlineColor), trackOutlineColor: MaterialStatePropertyAll<Color>(globalThemeOutlineColor),
trackOutlineWidth: MaterialStatePropertyAll<double>(globalThemeOutlineWidth),
), ),
); );
final bool material3 = themeData.useMaterial3; final bool material3 = themeData.useMaterial3;
...@@ -555,6 +586,7 @@ void main() { ...@@ -555,6 +586,7 @@ void main() {
thumbColor: MaterialStatePropertyAll<Color>(localThemeThumbColor), thumbColor: MaterialStatePropertyAll<Color>(localThemeThumbColor),
trackColor: MaterialStatePropertyAll<Color>(localThemeTrackColor), trackColor: MaterialStatePropertyAll<Color>(localThemeTrackColor),
trackOutlineColor: MaterialStatePropertyAll<Color>(localThemeOutlineColor), trackOutlineColor: MaterialStatePropertyAll<Color>(localThemeOutlineColor),
trackOutlineWidth: MaterialStatePropertyAll<double>(localThemeOutlineWidth)
), ),
child: Switch( child: Switch(
value: selected, value: selected,
...@@ -573,11 +605,11 @@ void main() { ...@@ -573,11 +605,11 @@ void main() {
material3 material3
? (paints ? (paints
..rrect(color: localThemeTrackColor) ..rrect(color: localThemeTrackColor)
..rrect(color: localThemeOutlineColor) ..rrect(color: localThemeOutlineColor, strokeWidth: localThemeOutlineWidth)
..rrect(color: localThemeThumbColor)) ..rrect(color: localThemeThumbColor))
: (paints : (paints
..rrect(color: localThemeTrackColor) ..rrect(color: localThemeTrackColor)
..rrect(color: localThemeOutlineColor) ..rrect(color: localThemeOutlineColor, strokeWidth: localThemeOutlineWidth)
..rrect() ..rrect()
..rrect() ..rrect()
..rrect() ..rrect()
......
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