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;
|
final ValueChanged<bool>? onChanged;
|
||||||
|
|
||||||
|
/// {@template flutter.material.switch.activeColor}
|
||||||
/// The color to use when this switch is on.
|
/// The color to use when this switch is on.
|
||||||
|
/// {@endtemplate}
|
||||||
///
|
///
|
||||||
/// Defaults to [ColorScheme.secondary].
|
/// Defaults to [ColorScheme.secondary].
|
||||||
///
|
///
|
||||||
@ -205,7 +207,9 @@ class Switch extends StatelessWidget {
|
|||||||
/// state, it will be used instead of this color.
|
/// state, it will be used instead of this color.
|
||||||
final Color? activeColor;
|
final Color? activeColor;
|
||||||
|
|
||||||
|
/// {@template flutter.material.switch.activeTrackColor}
|
||||||
/// The color to use on the track when this switch is on.
|
/// The color to use on the track when this switch is on.
|
||||||
|
/// {@endtemplate}
|
||||||
///
|
///
|
||||||
/// Defaults to [ColorScheme.secondary] with the opacity set at 50%.
|
/// 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.
|
/// state, it will be used instead of this color.
|
||||||
final Color? activeTrackColor;
|
final Color? activeTrackColor;
|
||||||
|
|
||||||
|
/// {@template flutter.material.switch.inactiveThumbColor}
|
||||||
/// The color to use on the thumb when this switch is off.
|
/// The color to use on the thumb when this switch is off.
|
||||||
|
/// {@endtemplate}
|
||||||
///
|
///
|
||||||
/// Defaults to the colors described in the Material design specification.
|
/// Defaults to the colors described in the Material design specification.
|
||||||
///
|
///
|
||||||
@ -225,7 +231,9 @@ class Switch extends StatelessWidget {
|
|||||||
/// used instead of this color.
|
/// used instead of this color.
|
||||||
final Color? inactiveThumbColor;
|
final Color? inactiveThumbColor;
|
||||||
|
|
||||||
|
/// {@template flutter.material.switch.inactiveTrackColor}
|
||||||
/// The color to use on the track when this switch is off.
|
/// The color to use on the track when this switch is off.
|
||||||
|
/// {@endtemplate}
|
||||||
///
|
///
|
||||||
/// Defaults to the colors described in the Material design specification.
|
/// Defaults to the colors described in the Material design specification.
|
||||||
///
|
///
|
||||||
@ -235,22 +243,30 @@ class Switch extends StatelessWidget {
|
|||||||
/// used instead of this color.
|
/// used instead of this color.
|
||||||
final Color? inactiveTrackColor;
|
final Color? inactiveTrackColor;
|
||||||
|
|
||||||
|
/// {@template flutter.material.switch.activeThumbImage}
|
||||||
/// An image to use on the thumb of this switch when the switch is on.
|
/// 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].
|
/// Ignored if this switch is created with [Switch.adaptive].
|
||||||
final ImageProvider? activeThumbImage;
|
final ImageProvider? activeThumbImage;
|
||||||
|
|
||||||
|
/// {@template flutter.material.switch.onActiveThumbImageError}
|
||||||
/// An optional error callback for errors emitted when loading
|
/// An optional error callback for errors emitted when loading
|
||||||
/// [activeThumbImage].
|
/// [activeThumbImage].
|
||||||
|
/// {@endtemplate}
|
||||||
final ImageErrorListener? onActiveThumbImageError;
|
final ImageErrorListener? onActiveThumbImageError;
|
||||||
|
|
||||||
|
/// {@template flutter.material.switch.inactiveThumbImage}
|
||||||
/// An image to use on the thumb of this switch when the switch is off.
|
/// 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].
|
/// Ignored if this switch is created with [Switch.adaptive].
|
||||||
final ImageProvider? inactiveThumbImage;
|
final ImageProvider? inactiveThumbImage;
|
||||||
|
|
||||||
|
/// {@template flutter.material.switch.onInactiveThumbImageError}
|
||||||
/// An optional error callback for errors emitted when loading
|
/// An optional error callback for errors emitted when loading
|
||||||
/// [inactiveThumbImage].
|
/// [inactiveThumbImage].
|
||||||
|
/// {@endtemplate}
|
||||||
final ImageErrorListener? onInactiveThumbImageError;
|
final ImageErrorListener? onInactiveThumbImageError;
|
||||||
|
|
||||||
/// {@template flutter.material.switch.thumbColor}
|
/// {@template flutter.material.switch.thumbColor}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
import 'package:flutter/gestures.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
import 'list_tile.dart';
|
import 'list_tile.dart';
|
||||||
@ -163,13 +164,27 @@ class SwitchListTile extends StatelessWidget {
|
|||||||
super.key,
|
super.key,
|
||||||
required this.value,
|
required this.value,
|
||||||
required this.onChanged,
|
required this.onChanged,
|
||||||
this.tileColor,
|
|
||||||
this.activeColor,
|
this.activeColor,
|
||||||
this.activeTrackColor,
|
this.activeTrackColor,
|
||||||
this.inactiveThumbColor,
|
this.inactiveThumbColor,
|
||||||
this.inactiveTrackColor,
|
this.inactiveTrackColor,
|
||||||
this.activeThumbImage,
|
this.activeThumbImage,
|
||||||
|
this.onActiveThumbImageError,
|
||||||
this.inactiveThumbImage,
|
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.title,
|
||||||
this.subtitle,
|
this.subtitle,
|
||||||
this.isThreeLine = false,
|
this.isThreeLine = false,
|
||||||
@ -177,17 +192,16 @@ class SwitchListTile extends StatelessWidget {
|
|||||||
this.contentPadding,
|
this.contentPadding,
|
||||||
this.secondary,
|
this.secondary,
|
||||||
this.selected = false,
|
this.selected = false,
|
||||||
this.autofocus = false,
|
|
||||||
this.controlAffinity = ListTileControlAffinity.platform,
|
this.controlAffinity = ListTileControlAffinity.platform,
|
||||||
this.shape,
|
this.shape,
|
||||||
this.selectedTileColor,
|
this.selectedTileColor,
|
||||||
this.visualDensity,
|
this.visualDensity,
|
||||||
this.focusNode,
|
|
||||||
this.onFocusChange,
|
|
||||||
this.enableFeedback,
|
this.enableFeedback,
|
||||||
this.hoverColor,
|
this.hoverColor,
|
||||||
this.trackOutlineColor,
|
|
||||||
}) : _switchListTileType = _SwitchListTileType.material,
|
}) : _switchListTileType = _SwitchListTileType.material,
|
||||||
|
applyCupertinoTheme = false,
|
||||||
|
assert(activeThumbImage != null || onActiveThumbImageError == null),
|
||||||
|
assert(inactiveThumbImage != null || onInactiveThumbImageError == null),
|
||||||
assert(!isThreeLine || subtitle != null);
|
assert(!isThreeLine || subtitle != null);
|
||||||
|
|
||||||
/// Creates a Material [ListTile] with an adaptive [Switch], following
|
/// Creates a Material [ListTile] with an adaptive [Switch], following
|
||||||
@ -206,13 +220,28 @@ class SwitchListTile extends StatelessWidget {
|
|||||||
super.key,
|
super.key,
|
||||||
required this.value,
|
required this.value,
|
||||||
required this.onChanged,
|
required this.onChanged,
|
||||||
this.tileColor,
|
|
||||||
this.activeColor,
|
this.activeColor,
|
||||||
this.activeTrackColor,
|
this.activeTrackColor,
|
||||||
this.inactiveThumbColor,
|
this.inactiveThumbColor,
|
||||||
this.inactiveTrackColor,
|
this.inactiveTrackColor,
|
||||||
this.activeThumbImage,
|
this.activeThumbImage,
|
||||||
|
this.onActiveThumbImageError,
|
||||||
this.inactiveThumbImage,
|
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.title,
|
||||||
this.subtitle,
|
this.subtitle,
|
||||||
this.isThreeLine = false,
|
this.isThreeLine = false,
|
||||||
@ -220,18 +249,16 @@ class SwitchListTile extends StatelessWidget {
|
|||||||
this.contentPadding,
|
this.contentPadding,
|
||||||
this.secondary,
|
this.secondary,
|
||||||
this.selected = false,
|
this.selected = false,
|
||||||
this.autofocus = false,
|
|
||||||
this.controlAffinity = ListTileControlAffinity.platform,
|
this.controlAffinity = ListTileControlAffinity.platform,
|
||||||
this.shape,
|
this.shape,
|
||||||
this.selectedTileColor,
|
this.selectedTileColor,
|
||||||
this.visualDensity,
|
this.visualDensity,
|
||||||
this.focusNode,
|
|
||||||
this.onFocusChange,
|
|
||||||
this.enableFeedback,
|
this.enableFeedback,
|
||||||
this.hoverColor,
|
this.hoverColor,
|
||||||
this.trackOutlineColor,
|
|
||||||
}) : _switchListTileType = _SwitchListTileType.adaptive,
|
}) : _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.
|
/// Whether this switch is checked.
|
||||||
///
|
///
|
||||||
@ -265,43 +292,146 @@ class SwitchListTile extends StatelessWidget {
|
|||||||
/// {@end-tool}
|
/// {@end-tool}
|
||||||
final ValueChanged<bool>? onChanged;
|
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].
|
/// Defaults to [ColorScheme.secondary] of the current [Theme].
|
||||||
final Color? activeColor;
|
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%.
|
/// Defaults to [ThemeData.toggleableActiveColor] with the opacity set at 50%.
|
||||||
///
|
///
|
||||||
/// Ignored if created with [SwitchListTile.adaptive].
|
/// Ignored if created with [SwitchListTile.adaptive].
|
||||||
final Color? activeTrackColor;
|
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.
|
/// Defaults to the colors described in the Material design specification.
|
||||||
///
|
///
|
||||||
/// Ignored if created with [SwitchListTile.adaptive].
|
/// Ignored if created with [SwitchListTile.adaptive].
|
||||||
final Color? inactiveThumbColor;
|
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.
|
/// Defaults to the colors described in the Material design specification.
|
||||||
///
|
///
|
||||||
/// Ignored if created with [SwitchListTile.adaptive].
|
/// Ignored if created with [SwitchListTile.adaptive].
|
||||||
final Color? inactiveTrackColor;
|
final Color? inactiveTrackColor;
|
||||||
|
|
||||||
/// {@macro flutter.material.ListTile.tileColor}
|
/// {@macro flutter.material.switch.activeThumbImage}
|
||||||
final Color? tileColor;
|
|
||||||
|
|
||||||
/// An image to use on the thumb of this switch when the switch is on.
|
|
||||||
final ImageProvider? 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].
|
/// Ignored if created with [SwitchListTile.adaptive].
|
||||||
final ImageProvider? inactiveThumbImage;
|
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.
|
/// The primary content of the list tile.
|
||||||
///
|
///
|
||||||
/// Typically a [Text] widget.
|
/// Typically a [Text] widget.
|
||||||
@ -346,9 +476,6 @@ class SwitchListTile extends StatelessWidget {
|
|||||||
/// Normally, this property is left to its default value, false.
|
/// Normally, this property is left to its default value, false.
|
||||||
final bool selected;
|
final bool selected;
|
||||||
|
|
||||||
/// {@macro flutter.widgets.Focus.autofocus}
|
|
||||||
final bool autofocus;
|
|
||||||
|
|
||||||
/// If adaptive, creates the switch with [Switch.adaptive].
|
/// If adaptive, creates the switch with [Switch.adaptive].
|
||||||
final _SwitchListTileType _switchListTileType;
|
final _SwitchListTileType _switchListTileType;
|
||||||
|
|
||||||
@ -368,12 +495,6 @@ class SwitchListTile extends StatelessWidget {
|
|||||||
/// {@macro flutter.material.themedata.visualDensity}
|
/// {@macro flutter.material.themedata.visualDensity}
|
||||||
final VisualDensity? 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}
|
/// {@macro flutter.material.ListTile.enableFeedback}
|
||||||
///
|
///
|
||||||
/// See also:
|
/// See also:
|
||||||
@ -384,15 +505,8 @@ class SwitchListTile extends StatelessWidget {
|
|||||||
/// The color for the tile's [Material] when a pointer is hovering over it.
|
/// The color for the tile's [Material] when a pointer is hovering over it.
|
||||||
final Color? hoverColor;
|
final Color? hoverColor;
|
||||||
|
|
||||||
/// {@macro flutter.material.switch.trackOutlineColor}
|
/// {@macro flutter.cupertino.CupertinoSwitch.applyTheme}
|
||||||
///
|
final bool? applyCupertinoTheme;
|
||||||
/// 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;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -405,13 +519,23 @@ class SwitchListTile extends StatelessWidget {
|
|||||||
activeColor: activeColor,
|
activeColor: activeColor,
|
||||||
activeThumbImage: activeThumbImage,
|
activeThumbImage: activeThumbImage,
|
||||||
inactiveThumbImage: inactiveThumbImage,
|
inactiveThumbImage: inactiveThumbImage,
|
||||||
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
materialTapTargetSize: materialTapTargetSize ?? MaterialTapTargetSize.shrinkWrap,
|
||||||
activeTrackColor: activeTrackColor,
|
activeTrackColor: activeTrackColor,
|
||||||
inactiveTrackColor: inactiveTrackColor,
|
inactiveTrackColor: inactiveTrackColor,
|
||||||
inactiveThumbColor: inactiveThumbColor,
|
inactiveThumbColor: inactiveThumbColor,
|
||||||
autofocus: autofocus,
|
autofocus: autofocus,
|
||||||
onFocusChange: onFocusChange,
|
onFocusChange: onFocusChange,
|
||||||
|
onActiveThumbImageError: onActiveThumbImageError,
|
||||||
|
onInactiveThumbImageError: onInactiveThumbImageError,
|
||||||
|
thumbColor: thumbColor,
|
||||||
|
trackColor: trackColor,
|
||||||
trackOutlineColor: trackOutlineColor,
|
trackOutlineColor: trackOutlineColor,
|
||||||
|
thumbIcon: thumbIcon,
|
||||||
|
applyCupertinoTheme: applyCupertinoTheme,
|
||||||
|
dragStartBehavior: dragStartBehavior,
|
||||||
|
mouseCursor: mouseCursor,
|
||||||
|
splashRadius: splashRadius,
|
||||||
|
overlayColor: overlayColor,
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -422,13 +546,22 @@ class SwitchListTile extends StatelessWidget {
|
|||||||
activeColor: activeColor,
|
activeColor: activeColor,
|
||||||
activeThumbImage: activeThumbImage,
|
activeThumbImage: activeThumbImage,
|
||||||
inactiveThumbImage: inactiveThumbImage,
|
inactiveThumbImage: inactiveThumbImage,
|
||||||
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
materialTapTargetSize: materialTapTargetSize ?? MaterialTapTargetSize.shrinkWrap,
|
||||||
activeTrackColor: activeTrackColor,
|
activeTrackColor: activeTrackColor,
|
||||||
inactiveTrackColor: inactiveTrackColor,
|
inactiveTrackColor: inactiveTrackColor,
|
||||||
inactiveThumbColor: inactiveThumbColor,
|
inactiveThumbColor: inactiveThumbColor,
|
||||||
autofocus: autofocus,
|
autofocus: autofocus,
|
||||||
onFocusChange: onFocusChange,
|
onFocusChange: onFocusChange,
|
||||||
|
onActiveThumbImageError: onActiveThumbImageError,
|
||||||
|
onInactiveThumbImageError: onInactiveThumbImageError,
|
||||||
|
thumbColor: thumbColor,
|
||||||
|
trackColor: trackColor,
|
||||||
trackOutlineColor: trackOutlineColor,
|
trackOutlineColor: trackOutlineColor,
|
||||||
|
thumbIcon: thumbIcon,
|
||||||
|
dragStartBehavior: dragStartBehavior,
|
||||||
|
mouseCursor: mouseCursor,
|
||||||
|
splashRadius: splashRadius,
|
||||||
|
overlayColor: overlayColor,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -603,19 +603,660 @@ void main() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Start hovering
|
// 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 gesture.moveTo(tester.getCenter(find.byKey(key)));
|
||||||
|
|
||||||
await tester.pump();
|
await tester.pump();
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
expect(
|
expect(
|
||||||
Material.of(tester.element(find.byKey(key))),
|
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
|
paints
|
||||||
..rect()
|
..rrect()..rrect()..rrect()..rrect()
|
||||||
..rect(
|
..rrect(color: activeDisabledThumbColor),
|
||||||
color: Colors.orange[500],
|
);
|
||||||
rect: const Rect.fromLTRB(350.0, 250.0, 450.0, 350.0),
|
|
||||||
)
|
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