Add missing parameters to SwitchListTile
(#120115)
* Add missing parameters to SwitchListTile * Update SwitchListTile doc * Update doc for existing APIs * Address comment * Fix typo --------- Co-authored-by: Qun Cheng <quncheng@google.com>
This commit is contained in:
parent
9996126740
commit
5e506aeb61
@ -197,7 +197,9 @@ class Switch extends StatelessWidget {
|
||||
/// ```
|
||||
final ValueChanged<bool>? onChanged;
|
||||
|
||||
/// {@template flutter.material.switch.activeColor}
|
||||
/// The color to use when this switch is on.
|
||||
/// {@endtemplate}
|
||||
///
|
||||
/// Defaults to [ColorScheme.secondary].
|
||||
///
|
||||
@ -205,7 +207,9 @@ class Switch extends StatelessWidget {
|
||||
/// state, it will be used instead of this color.
|
||||
final Color? activeColor;
|
||||
|
||||
/// {@template flutter.material.switch.activeTrackColor}
|
||||
/// The color to use on the track when this switch is on.
|
||||
/// {@endtemplate}
|
||||
///
|
||||
/// Defaults to [ColorScheme.secondary] with the opacity set at 50%.
|
||||
///
|
||||
@ -215,7 +219,9 @@ class Switch extends StatelessWidget {
|
||||
/// state, it will be used instead of this color.
|
||||
final Color? activeTrackColor;
|
||||
|
||||
/// {@template flutter.material.switch.inactiveThumbColor}
|
||||
/// The color to use on the thumb when this switch is off.
|
||||
/// {@endtemplate}
|
||||
///
|
||||
/// Defaults to the colors described in the Material design specification.
|
||||
///
|
||||
@ -225,7 +231,9 @@ class Switch extends StatelessWidget {
|
||||
/// used instead of this color.
|
||||
final Color? inactiveThumbColor;
|
||||
|
||||
/// {@template flutter.material.switch.inactiveTrackColor}
|
||||
/// The color to use on the track when this switch is off.
|
||||
/// {@endtemplate}
|
||||
///
|
||||
/// Defaults to the colors described in the Material design specification.
|
||||
///
|
||||
@ -235,22 +243,30 @@ class Switch extends StatelessWidget {
|
||||
/// used instead of this color.
|
||||
final Color? inactiveTrackColor;
|
||||
|
||||
/// {@template flutter.material.switch.activeThumbImage}
|
||||
/// An image to use on the thumb of this switch when the switch is on.
|
||||
/// {@endtemplate}
|
||||
///
|
||||
/// Ignored if this switch is created with [Switch.adaptive].
|
||||
final ImageProvider? activeThumbImage;
|
||||
|
||||
/// {@template flutter.material.switch.onActiveThumbImageError}
|
||||
/// An optional error callback for errors emitted when loading
|
||||
/// [activeThumbImage].
|
||||
/// {@endtemplate}
|
||||
final ImageErrorListener? onActiveThumbImageError;
|
||||
|
||||
/// {@template flutter.material.switch.inactiveThumbImage}
|
||||
/// An image to use on the thumb of this switch when the switch is off.
|
||||
/// {@endtemplate}
|
||||
///
|
||||
/// Ignored if this switch is created with [Switch.adaptive].
|
||||
final ImageProvider? inactiveThumbImage;
|
||||
|
||||
/// {@template flutter.material.switch.onInactiveThumbImageError}
|
||||
/// An optional error callback for errors emitted when loading
|
||||
/// [inactiveThumbImage].
|
||||
/// {@endtemplate}
|
||||
final ImageErrorListener? onInactiveThumbImageError;
|
||||
|
||||
/// {@template flutter.material.switch.thumbColor}
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'list_tile.dart';
|
||||
@ -163,13 +164,27 @@ class SwitchListTile extends StatelessWidget {
|
||||
super.key,
|
||||
required this.value,
|
||||
required this.onChanged,
|
||||
this.tileColor,
|
||||
this.activeColor,
|
||||
this.activeTrackColor,
|
||||
this.inactiveThumbColor,
|
||||
this.inactiveTrackColor,
|
||||
this.activeThumbImage,
|
||||
this.onActiveThumbImageError,
|
||||
this.inactiveThumbImage,
|
||||
this.onInactiveThumbImageError,
|
||||
this.thumbColor,
|
||||
this.trackColor,
|
||||
this.trackOutlineColor,
|
||||
this.thumbIcon,
|
||||
this.materialTapTargetSize,
|
||||
this.dragStartBehavior = DragStartBehavior.start,
|
||||
this.mouseCursor,
|
||||
this.overlayColor,
|
||||
this.splashRadius,
|
||||
this.focusNode,
|
||||
this.onFocusChange,
|
||||
this.autofocus = false,
|
||||
this.tileColor,
|
||||
this.title,
|
||||
this.subtitle,
|
||||
this.isThreeLine = false,
|
||||
@ -177,17 +192,16 @@ class SwitchListTile extends StatelessWidget {
|
||||
this.contentPadding,
|
||||
this.secondary,
|
||||
this.selected = false,
|
||||
this.autofocus = false,
|
||||
this.controlAffinity = ListTileControlAffinity.platform,
|
||||
this.shape,
|
||||
this.selectedTileColor,
|
||||
this.visualDensity,
|
||||
this.focusNode,
|
||||
this.onFocusChange,
|
||||
this.enableFeedback,
|
||||
this.hoverColor,
|
||||
this.trackOutlineColor,
|
||||
}) : _switchListTileType = _SwitchListTileType.material,
|
||||
applyCupertinoTheme = false,
|
||||
assert(activeThumbImage != null || onActiveThumbImageError == null),
|
||||
assert(inactiveThumbImage != null || onInactiveThumbImageError == null),
|
||||
assert(!isThreeLine || subtitle != null);
|
||||
|
||||
/// Creates a Material [ListTile] with an adaptive [Switch], following
|
||||
@ -206,13 +220,28 @@ class SwitchListTile extends StatelessWidget {
|
||||
super.key,
|
||||
required this.value,
|
||||
required this.onChanged,
|
||||
this.tileColor,
|
||||
this.activeColor,
|
||||
this.activeTrackColor,
|
||||
this.inactiveThumbColor,
|
||||
this.inactiveTrackColor,
|
||||
this.activeThumbImage,
|
||||
this.onActiveThumbImageError,
|
||||
this.inactiveThumbImage,
|
||||
this.onInactiveThumbImageError,
|
||||
this.thumbColor,
|
||||
this.trackColor,
|
||||
this.trackOutlineColor,
|
||||
this.thumbIcon,
|
||||
this.materialTapTargetSize,
|
||||
this.dragStartBehavior = DragStartBehavior.start,
|
||||
this.mouseCursor,
|
||||
this.overlayColor,
|
||||
this.splashRadius,
|
||||
this.focusNode,
|
||||
this.onFocusChange,
|
||||
this.autofocus = false,
|
||||
this.applyCupertinoTheme,
|
||||
this.tileColor,
|
||||
this.title,
|
||||
this.subtitle,
|
||||
this.isThreeLine = false,
|
||||
@ -220,18 +249,16 @@ class SwitchListTile extends StatelessWidget {
|
||||
this.contentPadding,
|
||||
this.secondary,
|
||||
this.selected = false,
|
||||
this.autofocus = false,
|
||||
this.controlAffinity = ListTileControlAffinity.platform,
|
||||
this.shape,
|
||||
this.selectedTileColor,
|
||||
this.visualDensity,
|
||||
this.focusNode,
|
||||
this.onFocusChange,
|
||||
this.enableFeedback,
|
||||
this.hoverColor,
|
||||
this.trackOutlineColor,
|
||||
}) : _switchListTileType = _SwitchListTileType.adaptive,
|
||||
assert(!isThreeLine || subtitle != null);
|
||||
assert(!isThreeLine || subtitle != null),
|
||||
assert(activeThumbImage != null || onActiveThumbImageError == null),
|
||||
assert(inactiveThumbImage != null || onInactiveThumbImageError == null);
|
||||
|
||||
/// Whether this switch is checked.
|
||||
///
|
||||
@ -265,43 +292,146 @@ class SwitchListTile extends StatelessWidget {
|
||||
/// {@end-tool}
|
||||
final ValueChanged<bool>? onChanged;
|
||||
|
||||
/// The color to use when this switch is on.
|
||||
/// {@macro flutter.material.switch.activeColor}
|
||||
///
|
||||
/// Defaults to [ColorScheme.secondary] of the current [Theme].
|
||||
final Color? activeColor;
|
||||
|
||||
/// The color to use on the track when this switch is on.
|
||||
/// {@macro flutter.material.switch.activeTrackColor}
|
||||
///
|
||||
/// Defaults to [ThemeData.toggleableActiveColor] with the opacity set at 50%.
|
||||
///
|
||||
/// Ignored if created with [SwitchListTile.adaptive].
|
||||
final Color? activeTrackColor;
|
||||
|
||||
/// The color to use on the thumb when this switch is off.
|
||||
/// {@macro flutter.material.switch.inactiveThumbColor}
|
||||
///
|
||||
/// Defaults to the colors described in the Material design specification.
|
||||
///
|
||||
/// Ignored if created with [SwitchListTile.adaptive].
|
||||
final Color? inactiveThumbColor;
|
||||
|
||||
/// The color to use on the track when this switch is off.
|
||||
/// {@macro flutter.material.switch.inactiveTrackColor}
|
||||
///
|
||||
/// Defaults to the colors described in the Material design specification.
|
||||
///
|
||||
/// Ignored if created with [SwitchListTile.adaptive].
|
||||
final Color? inactiveTrackColor;
|
||||
|
||||
/// {@macro flutter.material.ListTile.tileColor}
|
||||
final Color? tileColor;
|
||||
|
||||
/// An image to use on the thumb of this switch when the switch is on.
|
||||
/// {@macro flutter.material.switch.activeThumbImage}
|
||||
final ImageProvider? activeThumbImage;
|
||||
|
||||
/// An image to use on the thumb of this switch when the switch is off.
|
||||
/// {@macro flutter.material.switch.onActiveThumbImageError}
|
||||
final ImageErrorListener? onActiveThumbImageError;
|
||||
|
||||
/// {@macro flutter.material.switch.inactiveThumbImage}
|
||||
///
|
||||
/// Ignored if created with [SwitchListTile.adaptive].
|
||||
final ImageProvider? inactiveThumbImage;
|
||||
|
||||
/// {@macro flutter.material.switch.onInactiveThumbImageError}
|
||||
final ImageErrorListener? onInactiveThumbImageError;
|
||||
|
||||
/// The color of this switch's thumb.
|
||||
///
|
||||
/// Resolved in the following states:
|
||||
/// * [MaterialState.selected].
|
||||
/// * [MaterialState.hovered].
|
||||
/// * [MaterialState.disabled].
|
||||
///
|
||||
/// If null, then the value of [activeColor] is used in the selected state
|
||||
/// and [inactiveThumbColor] in the default state. If that is also null, then
|
||||
/// the value of [SwitchThemeData.thumbColor] is used. If that is also null,
|
||||
/// The default value is used.
|
||||
final MaterialStateProperty<Color?>? thumbColor;
|
||||
|
||||
/// The color of this switch's track.
|
||||
///
|
||||
/// Resolved in the following states:
|
||||
/// * [MaterialState.selected].
|
||||
/// * [MaterialState.hovered].
|
||||
/// * [MaterialState.disabled].
|
||||
///
|
||||
/// If null, then the value of [activeTrackColor] is used in the selected
|
||||
/// state and [inactiveTrackColor] in the default state. If that is also null,
|
||||
/// then the value of [SwitchThemeData.trackColor] is used. If that is also
|
||||
/// null, then the default value is used.
|
||||
final MaterialStateProperty<Color?>? trackColor;
|
||||
|
||||
/// {@macro flutter.material.switch.trackOutlineColor}
|
||||
///
|
||||
/// The [ListTile] will be focused when this [SwitchListTile] requests focus,
|
||||
/// so the focused outline color of the switch will be ignored.
|
||||
///
|
||||
/// In Material 3, the outline color defaults to transparent in the selected
|
||||
/// state and [ColorScheme.outline] in the unselected state. In Material 2,
|
||||
/// the [Switch] track has no outline.
|
||||
final MaterialStateProperty<Color?>? trackOutlineColor;
|
||||
|
||||
/// The icon to use on the thumb of this switch
|
||||
///
|
||||
/// Resolved in the following states:
|
||||
/// * [MaterialState.selected].
|
||||
/// * [MaterialState.hovered].
|
||||
/// * [MaterialState.disabled].
|
||||
///
|
||||
/// If null, then the value of [SwitchThemeData.thumbIcon] is used. If this is
|
||||
/// also null, then the [Switch] does not have any icons on the thumb.
|
||||
final MaterialStateProperty<Icon?>? thumbIcon;
|
||||
|
||||
/// {@macro flutter.material.switch.materialTapTargetSize}
|
||||
///
|
||||
/// defaults to [MaterialTapTargetSize.shrinkWrap].
|
||||
final MaterialTapTargetSize? materialTapTargetSize;
|
||||
|
||||
/// {@macro flutter.cupertino.CupertinoSwitch.dragStartBehavior}
|
||||
final DragStartBehavior dragStartBehavior;
|
||||
|
||||
/// The cursor for a mouse pointer when it enters or is hovering over the
|
||||
/// widget.
|
||||
///
|
||||
/// If [mouseCursor] is a [MaterialStateProperty<MouseCursor>],
|
||||
/// [MaterialStateProperty.resolve] is used for the following [MaterialState]s:
|
||||
///
|
||||
/// * [MaterialState.selected].
|
||||
/// * [MaterialState.hovered].
|
||||
/// * [MaterialState.disabled].
|
||||
///
|
||||
/// If null, then the value of [SwitchThemeData.mouseCursor] is used. If that
|
||||
/// is also null, then [MaterialStateMouseCursor.clickable] is used.
|
||||
final MouseCursor? mouseCursor;
|
||||
|
||||
/// The color for the switch's [Material].
|
||||
///
|
||||
/// Resolves in the following states:
|
||||
/// * [MaterialState.pressed].
|
||||
/// * [MaterialState.selected].
|
||||
/// * [MaterialState.hovered].
|
||||
///
|
||||
/// If null, then the value of [activeColor] with alpha [kRadialReactionAlpha]
|
||||
/// and [hoverColor] is used in the pressed and hovered state. If that is also
|
||||
/// null, the value of [SwitchThemeData.overlayColor] is used. If that is
|
||||
/// also null, then the default value is used in the pressed and hovered state.
|
||||
final MaterialStateProperty<Color?>? overlayColor;
|
||||
|
||||
/// {@macro flutter.material.switch.splashRadius}
|
||||
///
|
||||
/// If null, then the value of [SwitchThemeData.splashRadius] is used. If that
|
||||
/// is also null, then [kRadialReactionRadius] is used.
|
||||
final double? splashRadius;
|
||||
|
||||
/// {@macro flutter.widgets.Focus.focusNode}
|
||||
final FocusNode? focusNode;
|
||||
|
||||
/// {@macro flutter.material.inkwell.onFocusChange}
|
||||
final ValueChanged<bool>? onFocusChange;
|
||||
|
||||
/// {@macro flutter.widgets.Focus.autofocus}
|
||||
final bool autofocus;
|
||||
|
||||
/// {@macro flutter.material.ListTile.tileColor}
|
||||
final Color? tileColor;
|
||||
|
||||
/// The primary content of the list tile.
|
||||
///
|
||||
/// Typically a [Text] widget.
|
||||
@ -346,9 +476,6 @@ class SwitchListTile extends StatelessWidget {
|
||||
/// Normally, this property is left to its default value, false.
|
||||
final bool selected;
|
||||
|
||||
/// {@macro flutter.widgets.Focus.autofocus}
|
||||
final bool autofocus;
|
||||
|
||||
/// If adaptive, creates the switch with [Switch.adaptive].
|
||||
final _SwitchListTileType _switchListTileType;
|
||||
|
||||
@ -368,12 +495,6 @@ class SwitchListTile extends StatelessWidget {
|
||||
/// {@macro flutter.material.themedata.visualDensity}
|
||||
final VisualDensity? visualDensity;
|
||||
|
||||
/// {@macro flutter.widgets.Focus.focusNode}
|
||||
final FocusNode? focusNode;
|
||||
|
||||
/// {@macro flutter.material.inkwell.onFocusChange}
|
||||
final ValueChanged<bool>? onFocusChange;
|
||||
|
||||
/// {@macro flutter.material.ListTile.enableFeedback}
|
||||
///
|
||||
/// See also:
|
||||
@ -384,15 +505,8 @@ class SwitchListTile extends StatelessWidget {
|
||||
/// The color for the tile's [Material] when a pointer is hovering over it.
|
||||
final Color? hoverColor;
|
||||
|
||||
/// {@macro flutter.material.switch.trackOutlineColor}
|
||||
///
|
||||
/// The [ListTile] will be focused when this [SwitchListTile] requests focus,
|
||||
/// so the focused outline color of the switch will be ignored.
|
||||
///
|
||||
/// In Material 3, the outline color defaults to transparent in the selected
|
||||
/// state and [ColorScheme.outline] in the unselected state. In Material 2,
|
||||
/// the [Switch] track has no outline.
|
||||
final MaterialStateProperty<Color?>? trackOutlineColor;
|
||||
/// {@macro flutter.cupertino.CupertinoSwitch.applyTheme}
|
||||
final bool? applyCupertinoTheme;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -405,13 +519,23 @@ class SwitchListTile extends StatelessWidget {
|
||||
activeColor: activeColor,
|
||||
activeThumbImage: activeThumbImage,
|
||||
inactiveThumbImage: inactiveThumbImage,
|
||||
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
materialTapTargetSize: materialTapTargetSize ?? MaterialTapTargetSize.shrinkWrap,
|
||||
activeTrackColor: activeTrackColor,
|
||||
inactiveTrackColor: inactiveTrackColor,
|
||||
inactiveThumbColor: inactiveThumbColor,
|
||||
autofocus: autofocus,
|
||||
onFocusChange: onFocusChange,
|
||||
onActiveThumbImageError: onActiveThumbImageError,
|
||||
onInactiveThumbImageError: onInactiveThumbImageError,
|
||||
thumbColor: thumbColor,
|
||||
trackColor: trackColor,
|
||||
trackOutlineColor: trackOutlineColor,
|
||||
thumbIcon: thumbIcon,
|
||||
applyCupertinoTheme: applyCupertinoTheme,
|
||||
dragStartBehavior: dragStartBehavior,
|
||||
mouseCursor: mouseCursor,
|
||||
splashRadius: splashRadius,
|
||||
overlayColor: overlayColor,
|
||||
);
|
||||
break;
|
||||
|
||||
@ -422,13 +546,22 @@ class SwitchListTile extends StatelessWidget {
|
||||
activeColor: activeColor,
|
||||
activeThumbImage: activeThumbImage,
|
||||
inactiveThumbImage: inactiveThumbImage,
|
||||
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
materialTapTargetSize: materialTapTargetSize ?? MaterialTapTargetSize.shrinkWrap,
|
||||
activeTrackColor: activeTrackColor,
|
||||
inactiveTrackColor: inactiveTrackColor,
|
||||
inactiveThumbColor: inactiveThumbColor,
|
||||
autofocus: autofocus,
|
||||
onFocusChange: onFocusChange,
|
||||
onActiveThumbImageError: onActiveThumbImageError,
|
||||
onInactiveThumbImageError: onInactiveThumbImageError,
|
||||
thumbColor: thumbColor,
|
||||
trackColor: trackColor,
|
||||
trackOutlineColor: trackOutlineColor,
|
||||
thumbIcon: thumbIcon,
|
||||
dragStartBehavior: dragStartBehavior,
|
||||
mouseCursor: mouseCursor,
|
||||
splashRadius: splashRadius,
|
||||
overlayColor: overlayColor,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -603,19 +603,660 @@ void main() {
|
||||
);
|
||||
|
||||
// Start hovering
|
||||
final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
|
||||
final TestGesture gesture = await tester.createGesture(
|
||||
kind: PointerDeviceKind.mouse);
|
||||
await gesture.moveTo(tester.getCenter(find.byKey(key)));
|
||||
|
||||
await tester.pump();
|
||||
await tester.pumpAndSettle();
|
||||
expect(
|
||||
Material.of(tester.element(find.byKey(key))),
|
||||
paints..rect()..rect(
|
||||
color: Colors.orange[500],
|
||||
rect: const Rect.fromLTRB(350.0, 250.0, 450.0, 350.0),
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('SwitchListTile respects thumbColor in active/enabled states', (WidgetTester tester) async {
|
||||
const Color activeEnabledThumbColor = Color(0xFF000001);
|
||||
const Color activeDisabledThumbColor = Color(0xFF000002);
|
||||
const Color inactiveEnabledThumbColor = Color(0xFF000003);
|
||||
const Color inactiveDisabledThumbColor = Color(0xFF000004);
|
||||
|
||||
Color getThumbColor(Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.disabled)) {
|
||||
if (states.contains(MaterialState.selected)) {
|
||||
return activeDisabledThumbColor;
|
||||
}
|
||||
return inactiveDisabledThumbColor;
|
||||
}
|
||||
if (states.contains(MaterialState.selected)) {
|
||||
return activeEnabledThumbColor;
|
||||
}
|
||||
return inactiveEnabledThumbColor;
|
||||
}
|
||||
|
||||
final MaterialStateProperty<Color> thumbColor = MaterialStateColor.resolveWith(getThumbColor);
|
||||
|
||||
Widget buildSwitchListTile({required bool enabled, required bool selected}) {
|
||||
return wrap(
|
||||
child: StatefulBuilder(
|
||||
builder: (BuildContext context, StateSetter setState) {
|
||||
return SwitchListTile(
|
||||
value: selected,
|
||||
thumbColor: thumbColor,
|
||||
onChanged: enabled ? (_) { } : null,
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
await tester.pumpWidget(buildSwitchListTile(enabled: false, selected: false));
|
||||
await tester.pumpAndSettle();
|
||||
expect(
|
||||
Material.of(tester.element(find.byType(Switch))),
|
||||
paints
|
||||
..rrect()..rrect()..rrect()..rrect()
|
||||
..rrect(color: inactiveDisabledThumbColor),
|
||||
);
|
||||
|
||||
await tester.pumpWidget(buildSwitchListTile(enabled: false, selected: true));
|
||||
await tester.pumpAndSettle();
|
||||
expect(
|
||||
Material.of(tester.element(find.byType(Switch))),
|
||||
paints
|
||||
..rect()
|
||||
..rect(
|
||||
color: Colors.orange[500],
|
||||
rect: const Rect.fromLTRB(350.0, 250.0, 450.0, 350.0),
|
||||
)
|
||||
..rrect()..rrect()..rrect()..rrect()
|
||||
..rrect(color: activeDisabledThumbColor),
|
||||
);
|
||||
|
||||
await tester.pumpWidget(buildSwitchListTile(enabled: true, selected: false));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(
|
||||
Material.of(tester.element(find.byType(Switch))),
|
||||
paints
|
||||
..rrect()..rrect()..rrect()..rrect()
|
||||
..rrect(color: inactiveEnabledThumbColor),
|
||||
);
|
||||
|
||||
await tester.pumpWidget(buildSwitchListTile(enabled: true, selected: true));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(
|
||||
Material.of(tester.element(find.byType(Switch))),
|
||||
paints
|
||||
..rrect()..rrect()..rrect()..rrect()
|
||||
..rrect(color: activeEnabledThumbColor),
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('SwitchListTile respects thumbColor in hovered/pressed states', (WidgetTester tester) async {
|
||||
tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
|
||||
const Color hoveredThumbColor = Color(0xFF4caf50);
|
||||
const Color pressedThumbColor = Color(0xFFF44336);
|
||||
|
||||
Color getThumbColor(Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.pressed)) {
|
||||
return pressedThumbColor;
|
||||
}
|
||||
if (states.contains(MaterialState.hovered)) {
|
||||
return hoveredThumbColor;
|
||||
}
|
||||
return Colors.transparent;
|
||||
}
|
||||
|
||||
final MaterialStateProperty<Color> thumbColor = MaterialStateColor.resolveWith(getThumbColor);
|
||||
|
||||
Widget buildSwitchListTile() {
|
||||
return MaterialApp(
|
||||
theme: ThemeData(),
|
||||
home: wrap(
|
||||
child: StatefulBuilder(
|
||||
builder: (BuildContext context, StateSetter setState) {
|
||||
return SwitchListTile(
|
||||
value: false,
|
||||
thumbColor: thumbColor,
|
||||
onChanged: (_) { },
|
||||
);
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
await tester.pumpWidget(buildSwitchListTile());
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Start hovering
|
||||
final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
|
||||
await gesture.moveTo(tester.getCenter(find.byType(Switch)));
|
||||
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(
|
||||
Material.of(tester.element(find.byType(Switch))),
|
||||
paints
|
||||
..rrect()..rrect()..rrect()..rrect()
|
||||
..rrect(color: hoveredThumbColor),
|
||||
);
|
||||
|
||||
// On pressed state
|
||||
await tester.press(find.byType(Switch));
|
||||
await tester.pumpAndSettle();
|
||||
expect(
|
||||
Material.of(tester.element(find.byType(Switch))),
|
||||
paints
|
||||
..rrect()..rrect()..rrect()..rrect()
|
||||
..rrect(color: pressedThumbColor),
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('SwitchListTile respects trackColor in active/enabled states', (WidgetTester tester) async {
|
||||
const Color activeEnabledTrackColor = Color(0xFF000001);
|
||||
const Color activeDisabledTrackColor = Color(0xFF000002);
|
||||
const Color inactiveEnabledTrackColor = Color(0xFF000003);
|
||||
const Color inactiveDisabledTrackColor = Color(0xFF000004);
|
||||
|
||||
Color getTrackColor(Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.disabled)) {
|
||||
if (states.contains(MaterialState.selected)) {
|
||||
return activeDisabledTrackColor;
|
||||
}
|
||||
return inactiveDisabledTrackColor;
|
||||
}
|
||||
if (states.contains(MaterialState.selected)) {
|
||||
return activeEnabledTrackColor;
|
||||
}
|
||||
return inactiveEnabledTrackColor;
|
||||
}
|
||||
|
||||
final MaterialStateProperty<Color> trackColor = MaterialStateColor.resolveWith(getTrackColor);
|
||||
|
||||
Widget buildSwitchListTile({required bool enabled, required bool selected}) {
|
||||
return wrap(
|
||||
child: StatefulBuilder(
|
||||
builder: (BuildContext context, StateSetter setState) {
|
||||
return SwitchListTile(
|
||||
value: selected,
|
||||
trackColor: trackColor,
|
||||
onChanged: enabled ? (_) { } : null,
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
await tester.pumpWidget(buildSwitchListTile(enabled: false, selected: false));
|
||||
|
||||
expect(
|
||||
Material.of(tester.element(find.byType(Switch))),
|
||||
paints..rrect(color: inactiveDisabledTrackColor),
|
||||
);
|
||||
|
||||
await tester.pumpWidget(buildSwitchListTile(enabled: false, selected: true));
|
||||
await tester.pumpAndSettle();
|
||||
expect(
|
||||
Material.of(tester.element(find.byType(Switch))),
|
||||
paints..rrect(color: activeDisabledTrackColor),
|
||||
);
|
||||
|
||||
await tester.pumpWidget(buildSwitchListTile(enabled: true, selected: false));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(
|
||||
Material.of(tester.element(find.byType(Switch))),
|
||||
paints..rrect(color: inactiveEnabledTrackColor),
|
||||
);
|
||||
|
||||
await tester.pumpWidget(buildSwitchListTile(enabled: true, selected: true));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(
|
||||
Material.of(tester.element(find.byType(Switch))),
|
||||
paints..rrect(color: activeEnabledTrackColor),
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('SwitchListTile respects trackColor in hovered states', (WidgetTester tester) async {
|
||||
tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
|
||||
const Color hoveredTrackColor = Color(0xFF4caf50);
|
||||
|
||||
Color getTrackColor(Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.hovered)) {
|
||||
return hoveredTrackColor;
|
||||
}
|
||||
return Colors.transparent;
|
||||
}
|
||||
|
||||
final MaterialStateProperty<Color> trackColor = MaterialStateColor.resolveWith(getTrackColor);
|
||||
|
||||
Widget buildSwitchListTile() {
|
||||
return wrap(
|
||||
child: StatefulBuilder(
|
||||
builder: (BuildContext context, StateSetter setState) {
|
||||
return SwitchListTile(
|
||||
value: false,
|
||||
trackColor: trackColor,
|
||||
onChanged: (_) { },
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
await tester.pumpWidget(buildSwitchListTile());
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Start hovering
|
||||
final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
|
||||
await gesture.moveTo(tester.getCenter(find.byType(Switch)));
|
||||
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(
|
||||
Material.of(tester.element(find.byType(Switch))),
|
||||
paints..rrect(color: hoveredTrackColor),
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('SwitchListTile respects thumbIcon - M3', (WidgetTester tester) async {
|
||||
const Icon activeIcon = Icon(Icons.check);
|
||||
const Icon inactiveIcon = Icon(Icons.close);
|
||||
|
||||
MaterialStateProperty<Icon?> thumbIcon(Icon? activeIcon, Icon? inactiveIcon) {
|
||||
return MaterialStateProperty.resolveWith<Icon?>((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.selected)) {
|
||||
return activeIcon;
|
||||
}
|
||||
return inactiveIcon;
|
||||
});
|
||||
}
|
||||
|
||||
Widget buildSwitchListTile({required bool enabled, required bool active, Icon? activeIcon, Icon? inactiveIcon}) {
|
||||
return MaterialApp(
|
||||
theme: ThemeData(useMaterial3: true),
|
||||
home: wrap(
|
||||
child: StatefulBuilder(
|
||||
builder: (BuildContext context, StateSetter setState) {
|
||||
return SwitchListTile(
|
||||
thumbIcon: thumbIcon(activeIcon, inactiveIcon),
|
||||
value: active,
|
||||
onChanged: enabled ? (_) {} : null,
|
||||
);
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// active icon shows when switch is on.
|
||||
await tester.pumpWidget(buildSwitchListTile(enabled: true, active: true, activeIcon: activeIcon));
|
||||
await tester.pumpAndSettle();
|
||||
final Switch switchWidget0 = tester.widget<Switch>(find.byType(Switch));
|
||||
expect(switchWidget0.thumbIcon?.resolve(<MaterialState>{MaterialState.selected}), activeIcon);
|
||||
expect(
|
||||
Material.of(tester.element(find.byType(Switch))),
|
||||
paints
|
||||
..rrect()..rrect()
|
||||
..paragraph(offset: const Offset(32.0, 12.0)),
|
||||
);
|
||||
|
||||
// inactive icon shows when switch is off.
|
||||
await tester.pumpWidget(buildSwitchListTile(enabled: true, active: false, inactiveIcon: inactiveIcon));
|
||||
await tester.pumpAndSettle();
|
||||
final Switch switchWidget1 = tester.widget<Switch>(find.byType(Switch));
|
||||
expect(switchWidget1.thumbIcon?.resolve(<MaterialState>{}), inactiveIcon);
|
||||
expect(
|
||||
Material.of(tester.element(find.byType(Switch))),
|
||||
paints
|
||||
..rrect()..rrect()
|
||||
..rrect()
|
||||
..paragraph(offset: const Offset(12.0, 12.0)),
|
||||
);
|
||||
|
||||
// active icon doesn't show when switch is off.
|
||||
await tester.pumpWidget(buildSwitchListTile(enabled: true, active: false, activeIcon: activeIcon));
|
||||
await tester.pumpAndSettle();
|
||||
final Switch switchWidget2 = tester.widget<Switch>(find.byType(Switch));
|
||||
expect(switchWidget2.thumbIcon?.resolve(<MaterialState>{MaterialState.selected}), activeIcon);
|
||||
expect(
|
||||
Material.of(tester.element(find.byType(Switch))),
|
||||
paints
|
||||
..rrect()..rrect()..rrect()
|
||||
);
|
||||
|
||||
// inactive icon doesn't show when switch is on.
|
||||
await tester.pumpWidget(buildSwitchListTile(enabled: true, active: true, inactiveIcon: inactiveIcon));
|
||||
await tester.pumpAndSettle();
|
||||
final Switch switchWidget3 = tester.widget<Switch>(find.byType(Switch));
|
||||
expect(switchWidget3.thumbIcon?.resolve(<MaterialState>{}), inactiveIcon);
|
||||
expect(
|
||||
Material.of(tester.element(find.byType(Switch))),
|
||||
paints
|
||||
..rrect()..rrect()..restore(),
|
||||
);
|
||||
|
||||
// without icon
|
||||
await tester.pumpWidget(buildSwitchListTile(enabled: true, active: false));
|
||||
expect(
|
||||
Material.of(tester.element(find.byType(Switch))),
|
||||
paints
|
||||
..rrect()..rrect()..rrect()..restore(),
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('SwitchListTile respects materialTapTargetSize', (WidgetTester tester) async {
|
||||
Widget buildSwitchListTile(MaterialTapTargetSize materialTapTargetSize) {
|
||||
return wrap(
|
||||
child: StatefulBuilder(
|
||||
builder: (BuildContext context, StateSetter setState) {
|
||||
return SwitchListTile(
|
||||
materialTapTargetSize: materialTapTargetSize,
|
||||
value: false,
|
||||
onChanged: (_) {},
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
await tester.pumpWidget(buildSwitchListTile(MaterialTapTargetSize.padded));
|
||||
final Switch switchWidget = tester.widget<Switch>(find.byType(Switch));
|
||||
expect(switchWidget.materialTapTargetSize, MaterialTapTargetSize.padded);
|
||||
expect(tester.getSize(find.byType(Switch)), const Size(59.0, 48.0));
|
||||
|
||||
await tester.pumpWidget(buildSwitchListTile(MaterialTapTargetSize.shrinkWrap));
|
||||
final Switch switchWidget1 = tester.widget<Switch>(find.byType(Switch));
|
||||
expect(switchWidget1.materialTapTargetSize, MaterialTapTargetSize.shrinkWrap);
|
||||
expect(tester.getSize(find.byType(Switch)), const Size(59.0, 40.0));
|
||||
});
|
||||
|
||||
testWidgets('SwitchListTile.adaptive respects applyCupertinoTheme', (WidgetTester tester) async {
|
||||
final ThemeData theme = ThemeData();
|
||||
Widget buildSwitchListTile(bool applyCupertinoTheme, TargetPlatform platform) {
|
||||
return MaterialApp(
|
||||
theme: theme.copyWith(platform: platform),
|
||||
home: wrap(
|
||||
child: StatefulBuilder(
|
||||
builder: (BuildContext context, StateSetter setState) {
|
||||
return SwitchListTile.adaptive(
|
||||
applyCupertinoTheme: applyCupertinoTheme,
|
||||
value: true,
|
||||
onChanged: (_) {},
|
||||
);
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
for (final TargetPlatform platform in <TargetPlatform>[ TargetPlatform.iOS, TargetPlatform.macOS ]) {
|
||||
await tester.pumpWidget(buildSwitchListTile(true, platform));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.byType(CupertinoSwitch), findsOneWidget);
|
||||
expect(
|
||||
Material.of(tester.element(find.byType(Switch))),
|
||||
paints..rrect(color: theme.useMaterial3 ? const Color(0xFF6750A4) : const Color(0xFF2196F3)),
|
||||
);
|
||||
|
||||
await tester.pumpWidget(buildSwitchListTile(false, platform));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.byType(CupertinoSwitch), findsOneWidget);
|
||||
expect(
|
||||
Material.of(tester.element(find.byType(Switch))),
|
||||
paints..rrect(color: const Color(0xFF34C759)),
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
testWidgets('SwitchListTile respects materialTapTargetSize', (WidgetTester tester) async {
|
||||
Widget buildSwitchListTile(MaterialTapTargetSize materialTapTargetSize) {
|
||||
return wrap(
|
||||
child: StatefulBuilder(
|
||||
builder: (BuildContext context, StateSetter setState) {
|
||||
return SwitchListTile(
|
||||
materialTapTargetSize: materialTapTargetSize,
|
||||
value: false,
|
||||
onChanged: (_) {},
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
await tester.pumpWidget(buildSwitchListTile(MaterialTapTargetSize.padded));
|
||||
final Switch switchWidget = tester.widget<Switch>(find.byType(Switch));
|
||||
expect(switchWidget.materialTapTargetSize, MaterialTapTargetSize.padded);
|
||||
expect(tester.getSize(find.byType(Switch)), const Size(59.0, 48.0));
|
||||
|
||||
await tester.pumpWidget(buildSwitchListTile(MaterialTapTargetSize.shrinkWrap));
|
||||
final Switch switchWidget1 = tester.widget<Switch>(find.byType(Switch));
|
||||
expect(switchWidget1.materialTapTargetSize, MaterialTapTargetSize.shrinkWrap);
|
||||
expect(tester.getSize(find.byType(Switch)), const Size(59.0, 40.0));
|
||||
});
|
||||
|
||||
testWidgets('SwitchListTile passes the value of dragStartBehavior to Switch', (WidgetTester tester) async {
|
||||
Widget buildSwitchListTile(DragStartBehavior dragStartBehavior) {
|
||||
return wrap(
|
||||
child: StatefulBuilder(
|
||||
builder: (BuildContext context, StateSetter setState) {
|
||||
return SwitchListTile(
|
||||
dragStartBehavior: dragStartBehavior,
|
||||
value: false,
|
||||
onChanged: (_) {},
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
await tester.pumpWidget(buildSwitchListTile(DragStartBehavior.start));
|
||||
final Switch switchWidget = tester.widget<Switch>(find.byType(Switch));
|
||||
expect(switchWidget.dragStartBehavior, DragStartBehavior.start);
|
||||
|
||||
await tester.pumpWidget(buildSwitchListTile(DragStartBehavior.down));
|
||||
final Switch switchWidget1 = tester.widget<Switch>(find.byType(Switch));
|
||||
expect(switchWidget1.dragStartBehavior, DragStartBehavior.down);
|
||||
});
|
||||
|
||||
testWidgets('Switch on SwitchListTile changes mouse cursor when hovered', (WidgetTester tester) async {
|
||||
// Test SwitchListTile.adaptive() constructor
|
||||
await tester.pumpWidget(wrap(
|
||||
child: StatefulBuilder(
|
||||
builder: (BuildContext context, StateSetter setState) {
|
||||
return SwitchListTile.adaptive(
|
||||
mouseCursor: SystemMouseCursors.text,
|
||||
value: false,
|
||||
onChanged: (_) {},
|
||||
);
|
||||
}),
|
||||
));
|
||||
final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse, pointer: 1);
|
||||
await gesture.addPointer(location: tester.getCenter(find.byType(Switch)));
|
||||
|
||||
await tester.pump();
|
||||
|
||||
expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text);
|
||||
|
||||
// Test SwitchListTile() constructor
|
||||
await tester.pumpWidget(wrap(
|
||||
child: StatefulBuilder(
|
||||
builder: (BuildContext context, StateSetter setState) {
|
||||
return SwitchListTile(
|
||||
mouseCursor: SystemMouseCursors.forbidden,
|
||||
value: false,
|
||||
onChanged: (_) {},
|
||||
);
|
||||
}),
|
||||
));
|
||||
|
||||
await gesture.moveTo(tester.getCenter(find.byType(Switch)));
|
||||
expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.forbidden);
|
||||
|
||||
// Test default cursor
|
||||
await tester.pumpWidget(wrap(
|
||||
child: StatefulBuilder(
|
||||
builder: (BuildContext context, StateSetter setState) {
|
||||
return SwitchListTile(
|
||||
value: false,
|
||||
onChanged: (_) {},
|
||||
);
|
||||
}),
|
||||
));
|
||||
|
||||
expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.click);
|
||||
|
||||
// Test default cursor when disabled
|
||||
await tester.pumpWidget(wrap(
|
||||
child: StatefulBuilder(
|
||||
builder: (BuildContext context, StateSetter setState) {
|
||||
return const SwitchListTile(
|
||||
value: false,
|
||||
onChanged: null,
|
||||
);
|
||||
}),
|
||||
));
|
||||
|
||||
expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic);
|
||||
});
|
||||
|
||||
testWidgets('Switch with splash radius set', (WidgetTester tester) async {
|
||||
tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
|
||||
const double splashRadius = 35;
|
||||
await tester.pumpWidget(wrap(
|
||||
child: StatefulBuilder(
|
||||
builder: (BuildContext context, StateSetter setState) {
|
||||
return SwitchListTile(
|
||||
splashRadius: splashRadius,
|
||||
value: false,
|
||||
onChanged: (_) {},
|
||||
);
|
||||
}),
|
||||
));
|
||||
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
|
||||
await gesture.moveTo(tester.getCenter(find.byType(Switch)));
|
||||
|
||||
await tester.pumpAndSettle();
|
||||
expect(
|
||||
Material.of(tester.element(find.byType(Switch))),
|
||||
paints..circle(radius: splashRadius),
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('The overlay color for the thumb of the switch resolves in active/pressed/hovered states', (WidgetTester tester) async {
|
||||
tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
|
||||
const Color activeThumbColor = Color(0xFF000000);
|
||||
const Color inactiveThumbColor = Color(0xFF000010);
|
||||
const Color activePressedOverlayColor = Color(0xFF000001);
|
||||
const Color inactivePressedOverlayColor = Color(0xFF000002);
|
||||
const Color hoverOverlayColor = Color(0xFF000003);
|
||||
const Color hoverColor = Color(0xFF000005);
|
||||
|
||||
Color? getOverlayColor(Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.pressed)) {
|
||||
if (states.contains(MaterialState.selected)) {
|
||||
return activePressedOverlayColor;
|
||||
}
|
||||
return inactivePressedOverlayColor;
|
||||
}
|
||||
if (states.contains(MaterialState.hovered)) {
|
||||
return hoverOverlayColor;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Widget buildSwitch({bool active = false, bool focused = false, bool useOverlay = true}) {
|
||||
return MaterialApp(
|
||||
home: Scaffold(
|
||||
body: SwitchListTile(
|
||||
value: active,
|
||||
onChanged: (_) { },
|
||||
thumbColor: MaterialStateProperty.resolveWith<Color>((Set<MaterialState> states) {
|
||||
if (states.contains(MaterialState.selected)) {
|
||||
return activeThumbColor;
|
||||
}
|
||||
return inactiveThumbColor;
|
||||
}),
|
||||
overlayColor: useOverlay ? MaterialStateProperty.resolveWith(getOverlayColor) : null,
|
||||
hoverColor: hoverColor,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// test inactive Switch, and overlayColor is set to null.
|
||||
await tester.pumpWidget(buildSwitch(useOverlay: false));
|
||||
await tester.press(find.byType(Switch));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(
|
||||
Material.of(tester.element(find.byType(Switch))),
|
||||
paints
|
||||
..rrect()
|
||||
..circle(
|
||||
color: inactiveThumbColor.withAlpha(kRadialReactionAlpha),
|
||||
),
|
||||
reason: 'Default inactive pressed Switch should have overlay color from thumbColor',
|
||||
);
|
||||
|
||||
// test active Switch, and overlayColor is set to null.
|
||||
await tester.pumpWidget(buildSwitch(active: true, useOverlay: false));
|
||||
await tester.press(find.byType(Switch));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(
|
||||
Material.of(tester.element(find.byType(Switch))),
|
||||
paints
|
||||
..rrect()
|
||||
..circle(
|
||||
color: activeThumbColor.withAlpha(kRadialReactionAlpha),
|
||||
),
|
||||
reason: 'Default active pressed Switch should have overlay color from thumbColor',
|
||||
);
|
||||
|
||||
// test inactive Switch with an overlayColor
|
||||
await tester.pumpWidget(buildSwitch());
|
||||
await tester.press(find.byType(Switch));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(
|
||||
Material.of(tester.element(find.byType(Switch))),
|
||||
paints
|
||||
..rrect()
|
||||
..circle(
|
||||
color: inactivePressedOverlayColor,
|
||||
),
|
||||
reason: 'Inactive pressed Switch should have overlay color: $inactivePressedOverlayColor',
|
||||
);
|
||||
|
||||
// test active Switch with an overlayColor
|
||||
await tester.pumpWidget(buildSwitch(active: true));
|
||||
await tester.press(find.byType(Switch));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(
|
||||
Material.of(tester.element(find.byType(Switch))),
|
||||
paints
|
||||
..rrect()
|
||||
..circle(
|
||||
color: activePressedOverlayColor,
|
||||
),
|
||||
reason: 'Active pressed Switch should have overlay color: $activePressedOverlayColor',
|
||||
);
|
||||
|
||||
await tester.pumpWidget(buildSwitch(focused: true));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// 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()
|
||||
..circle(
|
||||
color: hoverOverlayColor,
|
||||
),
|
||||
reason: 'Hovered Switch should use overlay color $hoverOverlayColor over $hoverColor',
|
||||
);
|
||||
});
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user