Reland [a11y] CupertinoSwitch On/Off labels (#130173)
This original PR (https://github.com/flutter/flutter/pull/127776) was reverted (https://github.com/flutter/flutter/pull/130166) due to a Google test failure. This reopens the PR as per the discussion in https://github.com/flutter/flutter/pull/130166#issuecomment-1626105218. Fixes issue #4830.
This commit is contained in:
parent
3d67ca4311
commit
a189d95ac2
@ -75,6 +75,8 @@ class CupertinoSwitch extends StatefulWidget {
|
||||
this.thumbColor,
|
||||
this.applyTheme,
|
||||
this.focusColor,
|
||||
this.onLabelColor,
|
||||
this.offLabelColor,
|
||||
this.focusNode,
|
||||
this.onFocusChange,
|
||||
this.autofocus = false,
|
||||
@ -133,6 +135,17 @@ class CupertinoSwitch extends StatefulWidget {
|
||||
/// Defaults to a slightly transparent [activeColor].
|
||||
final Color? focusColor;
|
||||
|
||||
/// The color to use for the accessibility label when the switch is on.
|
||||
///
|
||||
/// Defaults to [CupertinoColors.white] when null.
|
||||
final Color? onLabelColor;
|
||||
|
||||
/// The color to use for the accessibility label when the switch is off.
|
||||
///
|
||||
/// Defaults to [Color.fromARGB(255, 179, 179, 179)]
|
||||
/// (or [Color.fromARGB(255, 255, 255, 255)] in high contrast) when null.
|
||||
final Color? offLabelColor;
|
||||
|
||||
/// {@macro flutter.widgets.Focus.focusNode}
|
||||
final FocusNode? focusNode;
|
||||
|
||||
@ -357,6 +370,19 @@ class _CupertinoSwitchState extends State<CupertinoSwitch> with TickerProviderSt
|
||||
?? CupertinoColors.systemGreen,
|
||||
context,
|
||||
);
|
||||
final (Color onLabelColor, Color offLabelColor)? onOffLabelColors =
|
||||
MediaQuery.onOffSwitchLabelsOf(context)
|
||||
? (
|
||||
CupertinoDynamicColor.resolve(
|
||||
widget.onLabelColor ?? CupertinoColors.white,
|
||||
context,
|
||||
),
|
||||
CupertinoDynamicColor.resolve(
|
||||
widget.offLabelColor ?? _kOffLabelColor,
|
||||
context,
|
||||
),
|
||||
)
|
||||
: null;
|
||||
if (needsPositionAnimation) {
|
||||
_resumePositionAnimation();
|
||||
}
|
||||
@ -389,6 +415,7 @@ class _CupertinoSwitchState extends State<CupertinoSwitch> with TickerProviderSt
|
||||
textDirection: Directionality.of(context),
|
||||
isFocused: isFocused,
|
||||
state: this,
|
||||
onOffLabelColors: onOffLabelColors,
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -417,6 +444,7 @@ class _CupertinoSwitchRenderObjectWidget extends LeafRenderObjectWidget {
|
||||
required this.textDirection,
|
||||
required this.isFocused,
|
||||
required this.state,
|
||||
required this.onOffLabelColors,
|
||||
});
|
||||
|
||||
final bool value;
|
||||
@ -428,6 +456,7 @@ class _CupertinoSwitchRenderObjectWidget extends LeafRenderObjectWidget {
|
||||
final _CupertinoSwitchState state;
|
||||
final TextDirection textDirection;
|
||||
final bool isFocused;
|
||||
final (Color onLabelColor, Color offLabelColor)? onOffLabelColors;
|
||||
|
||||
@override
|
||||
_RenderCupertinoSwitch createRenderObject(BuildContext context) {
|
||||
@ -441,6 +470,7 @@ class _CupertinoSwitchRenderObjectWidget extends LeafRenderObjectWidget {
|
||||
textDirection: textDirection,
|
||||
isFocused: isFocused,
|
||||
state: state,
|
||||
onOffLabelColors: onOffLabelColors,
|
||||
);
|
||||
}
|
||||
|
||||
@ -467,6 +497,24 @@ const double _kTrackInnerEnd = _kTrackWidth - _kTrackInnerStart;
|
||||
const double _kTrackInnerLength = _kTrackInnerEnd - _kTrackInnerStart;
|
||||
const double _kSwitchWidth = 59.0;
|
||||
const double _kSwitchHeight = 39.0;
|
||||
// Label sizes and padding taken from xcode inspector.
|
||||
// See https://github.com/flutter/flutter/issues/4830#issuecomment-528495360
|
||||
const double _kOnLabelWidth = 1.0;
|
||||
const double _kOnLabelHeight = 10.0;
|
||||
const double _kOnLabelPaddingHorizontal = 11.0;
|
||||
const double _kOffLabelWidth = 1.0;
|
||||
const double _kOffLabelPaddingHorizontal = 12.0;
|
||||
const double _kOffLabelRadius = 5.0;
|
||||
const CupertinoDynamicColor _kOffLabelColor = CupertinoDynamicColor.withBrightnessAndContrast(
|
||||
debugLabel: 'offSwitchLabel',
|
||||
// Source: https://github.com/flutter/flutter/pull/39993#discussion_r321946033
|
||||
color: Color.fromARGB(255, 179, 179, 179),
|
||||
// Source: https://github.com/flutter/flutter/pull/39993#issuecomment-535196665
|
||||
darkColor: Color.fromARGB(255, 179, 179, 179),
|
||||
// Source: https://github.com/flutter/flutter/pull/127776#discussion_r1244208264
|
||||
highContrastColor: Color.fromARGB(255, 255, 255, 255),
|
||||
darkHighContrastColor: Color.fromARGB(255, 255, 255, 255),
|
||||
);
|
||||
// Opacity of a disabled switch, as eye-balled from iOS Simulator on Mac.
|
||||
const double _kCupertinoSwitchDisabledOpacity = 0.5;
|
||||
|
||||
@ -484,6 +532,7 @@ class _RenderCupertinoSwitch extends RenderConstrainedBox {
|
||||
required TextDirection textDirection,
|
||||
required bool isFocused,
|
||||
required _CupertinoSwitchState state,
|
||||
required (Color onLabelColor, Color offLabelColor)? onOffLabelColors,
|
||||
}) : _value = value,
|
||||
_activeColor = activeColor,
|
||||
_trackColor = trackColor,
|
||||
@ -493,6 +542,7 @@ class _RenderCupertinoSwitch extends RenderConstrainedBox {
|
||||
_textDirection = textDirection,
|
||||
_isFocused = isFocused,
|
||||
_state = state,
|
||||
_onOffLabelColors = onOffLabelColors,
|
||||
super(additionalConstraints: const BoxConstraints.tightFor(width: _kSwitchWidth, height: _kSwitchHeight)) {
|
||||
state.position.addListener(markNeedsPaint);
|
||||
state._reaction.addListener(markNeedsPaint);
|
||||
@ -584,6 +634,16 @@ class _RenderCupertinoSwitch extends RenderConstrainedBox {
|
||||
markNeedsPaint();
|
||||
}
|
||||
|
||||
(Color onLabelColor, Color offLabelColor)? get onOffLabelColors => _onOffLabelColors;
|
||||
(Color onLabelColor, Color offLabelColor)? _onOffLabelColors;
|
||||
set onOffLabelColors((Color onLabelColor, Color offLabelColor)? value) {
|
||||
if (value == _onOffLabelColors) {
|
||||
return;
|
||||
}
|
||||
_onOffLabelColors = value;
|
||||
markNeedsPaint();
|
||||
}
|
||||
|
||||
bool get isInteractive => onChanged != null;
|
||||
|
||||
@override
|
||||
@ -649,6 +709,52 @@ class _RenderCupertinoSwitch extends RenderConstrainedBox {
|
||||
canvas.drawRRect(borderTrackRRect, borderPaint);
|
||||
}
|
||||
|
||||
if (_onOffLabelColors != null) {
|
||||
final (Color onLabelColor, Color offLabelColor) = onOffLabelColors!;
|
||||
|
||||
final double leftLabelOpacity = visualPosition * (1.0 - currentReactionValue);
|
||||
final double rightLabelOpacity = (1.0 - visualPosition) * (1.0 - currentReactionValue);
|
||||
final (double onLabelOpacity, double offLabelOpacity) =
|
||||
switch (textDirection) {
|
||||
TextDirection.ltr => (leftLabelOpacity, rightLabelOpacity),
|
||||
TextDirection.rtl => (rightLabelOpacity, leftLabelOpacity),
|
||||
};
|
||||
|
||||
final (Offset onLabelOffset, Offset offLabelOffset) =
|
||||
switch (textDirection) {
|
||||
TextDirection.ltr => (
|
||||
trackRect.centerLeft.translate(_kOnLabelPaddingHorizontal, 0),
|
||||
trackRect.centerRight.translate(-_kOffLabelPaddingHorizontal, 0),
|
||||
),
|
||||
TextDirection.rtl => (
|
||||
trackRect.centerRight.translate(-_kOnLabelPaddingHorizontal, 0),
|
||||
trackRect.centerLeft.translate(_kOffLabelPaddingHorizontal, 0),
|
||||
),
|
||||
};
|
||||
|
||||
// Draws '|' label
|
||||
final Rect onLabelRect = Rect.fromCenter(
|
||||
center: onLabelOffset,
|
||||
width: _kOnLabelWidth,
|
||||
height: _kOnLabelHeight,
|
||||
);
|
||||
final Paint onLabelPaint = Paint()
|
||||
..color = onLabelColor.withOpacity(onLabelOpacity)
|
||||
..style = PaintingStyle.fill;
|
||||
canvas.drawRect(onLabelRect, onLabelPaint);
|
||||
|
||||
// Draws 'O' label
|
||||
final Paint offLabelPaint = Paint()
|
||||
..color = offLabelColor.withOpacity(offLabelOpacity)
|
||||
..style = PaintingStyle.stroke
|
||||
..strokeWidth = _kOffLabelWidth;
|
||||
canvas.drawCircle(
|
||||
offLabelOffset,
|
||||
_kOffLabelRadius,
|
||||
offLabelPaint,
|
||||
);
|
||||
}
|
||||
|
||||
final double currentThumbExtension = CupertinoThumbPainter.extension * currentReactionValue;
|
||||
final double thumbLeft = lerpDouble(
|
||||
trackRect.left + _kTrackInnerStart - CupertinoThumbPainter.radius,
|
||||
|
@ -60,6 +60,8 @@ enum _MediaQueryAspect {
|
||||
invertColors,
|
||||
/// Specifies the aspect corresponding to [MediaQueryData.highContrast].
|
||||
highContrast,
|
||||
/// Specifies the aspect corresponding to [MediaQueryData.onOffSwitchLabels].
|
||||
onOffSwitchLabels,
|
||||
/// Specifies the aspect corresponding to [MediaQueryData.disableAnimations].
|
||||
disableAnimations,
|
||||
/// Specifies the aspect corresponding to [MediaQueryData.boldText].
|
||||
@ -153,6 +155,7 @@ class MediaQueryData {
|
||||
this.accessibleNavigation = false,
|
||||
this.invertColors = false,
|
||||
this.highContrast = false,
|
||||
this.onOffSwitchLabels = false,
|
||||
this.disableAnimations = false,
|
||||
this.boldText = false,
|
||||
this.navigationMode = NavigationMode.traditional,
|
||||
@ -220,6 +223,7 @@ class MediaQueryData {
|
||||
disableAnimations = platformData?.disableAnimations ?? view.platformDispatcher.accessibilityFeatures.disableAnimations,
|
||||
boldText = platformData?.boldText ?? view.platformDispatcher.accessibilityFeatures.boldText,
|
||||
highContrast = platformData?.highContrast ?? view.platformDispatcher.accessibilityFeatures.highContrast,
|
||||
onOffSwitchLabels = platformData?.onOffSwitchLabels ?? view.platformDispatcher.accessibilityFeatures.onOffSwitchLabels,
|
||||
alwaysUse24HourFormat = platformData?.alwaysUse24HourFormat ?? view.platformDispatcher.alwaysUse24HourFormat,
|
||||
navigationMode = platformData?.navigationMode ?? NavigationMode.traditional,
|
||||
gestureSettings = DeviceGestureSettings.fromView(view),
|
||||
@ -416,6 +420,15 @@ class MediaQueryData {
|
||||
/// or above.
|
||||
final bool highContrast;
|
||||
|
||||
/// Whether the user requested to show on/off labels inside switches on iOS,
|
||||
/// via Settings -> Accessibility -> Display & Text Size -> On/Off Labels.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [dart:ui.PlatformDispatcher.accessibilityFeatures], where the setting
|
||||
/// originates.
|
||||
final bool onOffSwitchLabels;
|
||||
|
||||
/// Whether the platform is requesting that animations be disabled or reduced
|
||||
/// as much as possible.
|
||||
///
|
||||
@ -488,6 +501,7 @@ class MediaQueryData {
|
||||
EdgeInsets? systemGestureInsets,
|
||||
bool? alwaysUse24HourFormat,
|
||||
bool? highContrast,
|
||||
bool? onOffSwitchLabels,
|
||||
bool? disableAnimations,
|
||||
bool? invertColors,
|
||||
bool? accessibleNavigation,
|
||||
@ -508,6 +522,7 @@ class MediaQueryData {
|
||||
alwaysUse24HourFormat: alwaysUse24HourFormat ?? this.alwaysUse24HourFormat,
|
||||
invertColors: invertColors ?? this.invertColors,
|
||||
highContrast: highContrast ?? this.highContrast,
|
||||
onOffSwitchLabels: onOffSwitchLabels ?? this.onOffSwitchLabels,
|
||||
disableAnimations: disableAnimations ?? this.disableAnimations,
|
||||
accessibleNavigation: accessibleNavigation ?? this.accessibleNavigation,
|
||||
boldText: boldText ?? this.boldText,
|
||||
@ -699,6 +714,7 @@ class MediaQueryData {
|
||||
&& other.systemGestureInsets == systemGestureInsets
|
||||
&& other.alwaysUse24HourFormat == alwaysUse24HourFormat
|
||||
&& other.highContrast == highContrast
|
||||
&& other.onOffSwitchLabels == onOffSwitchLabels
|
||||
&& other.disableAnimations == disableAnimations
|
||||
&& other.invertColors == invertColors
|
||||
&& other.accessibleNavigation == accessibleNavigation
|
||||
@ -719,6 +735,7 @@ class MediaQueryData {
|
||||
viewInsets,
|
||||
alwaysUse24HourFormat,
|
||||
highContrast,
|
||||
onOffSwitchLabels,
|
||||
disableAnimations,
|
||||
invertColors,
|
||||
accessibleNavigation,
|
||||
@ -742,6 +759,7 @@ class MediaQueryData {
|
||||
'alwaysUse24HourFormat: $alwaysUse24HourFormat',
|
||||
'accessibleNavigation: $accessibleNavigation',
|
||||
'highContrast: $highContrast',
|
||||
'onOffSwitchLabels: $onOffSwitchLabels',
|
||||
'disableAnimations: $disableAnimations',
|
||||
'invertColors: $invertColors',
|
||||
'boldText: $boldText',
|
||||
@ -1255,6 +1273,25 @@ class MediaQuery extends InheritedModel<_MediaQueryAspect> {
|
||||
/// the [MediaQueryData.highContrast] property of the ancestor [MediaQuery] changes.
|
||||
static bool? maybeHighContrastOf(BuildContext context) => _maybeOf(context, _MediaQueryAspect.highContrast)?.highContrast;
|
||||
|
||||
/// Returns onOffSwitchLabels for the nearest MediaQuery ancestor or false, if no
|
||||
/// such ancestor exists.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [MediaQueryData.onOffSwitchLabels], which indicates the platform's
|
||||
/// desire to show on/off labels inside switches.
|
||||
///
|
||||
/// Use of this method will cause the given [context] to rebuild any time that
|
||||
/// the [MediaQueryData.onOffSwitchLabels] property of the ancestor [MediaQuery] changes.
|
||||
static bool onOffSwitchLabelsOf(BuildContext context) => maybeOnOffSwitchLabelsOf(context) ?? false;
|
||||
|
||||
/// Returns onOffSwitchLabels for the nearest MediaQuery ancestor or
|
||||
/// null, if no such ancestor exists.
|
||||
///
|
||||
/// Use of this method will cause the given [context] to rebuild any time that
|
||||
/// the [MediaQueryData.onOffSwitchLabels] property of the ancestor [MediaQuery] changes.
|
||||
static bool? maybeOnOffSwitchLabelsOf(BuildContext context) => _maybeOf(context, _MediaQueryAspect.onOffSwitchLabels)?.onOffSwitchLabels;
|
||||
|
||||
/// Returns disableAnimations for the nearest MediaQuery ancestor or
|
||||
/// [Brightness.light], if no such ancestor exists.
|
||||
///
|
||||
@ -1406,6 +1443,10 @@ class MediaQuery extends InheritedModel<_MediaQueryAspect> {
|
||||
if (data.highContrast != oldWidget.data.highContrast) {
|
||||
return true;
|
||||
}
|
||||
case _MediaQueryAspect.onOffSwitchLabels:
|
||||
if (data.onOffSwitchLabels != oldWidget.data.onOffSwitchLabels) {
|
||||
return true;
|
||||
}
|
||||
case _MediaQueryAspect.disableAnimations:
|
||||
if (data.disableAnimations != oldWidget.data.disableAnimations) {
|
||||
return true;
|
||||
|
@ -753,6 +753,187 @@ void main() {
|
||||
);
|
||||
});
|
||||
|
||||
PaintPattern onLabelPaintPattern({
|
||||
required int alpha,
|
||||
bool isRtl = false,
|
||||
}) =>
|
||||
paints
|
||||
..rect(
|
||||
rect: Rect.fromLTWH(isRtl ? 43.5 : 14.5, 14.5, 1.0, 10.0),
|
||||
color: const Color(0xffffffff).withAlpha(alpha),
|
||||
style: PaintingStyle.fill,
|
||||
);
|
||||
|
||||
PaintPattern offLabelPaintPattern({
|
||||
required int alpha,
|
||||
bool highContrast = false,
|
||||
bool isRtl = false,
|
||||
}) =>
|
||||
paints
|
||||
..circle(
|
||||
x: isRtl ? 16.0 : 43.0,
|
||||
y: 19.5,
|
||||
radius: 5.0,
|
||||
color:
|
||||
(highContrast ? const Color(0xffffffff) : const Color(0xffb3b3b3))
|
||||
.withAlpha(alpha),
|
||||
strokeWidth: 1.0,
|
||||
style: PaintingStyle.stroke,
|
||||
);
|
||||
|
||||
testWidgets('Switch renders switch labels correctly before, during, and after being tapped', (WidgetTester tester) async {
|
||||
final Key switchKey = UniqueKey();
|
||||
bool value = false;
|
||||
await tester.pumpWidget(
|
||||
MediaQuery(
|
||||
data: const MediaQueryData(onOffSwitchLabels: true),
|
||||
child: Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: StatefulBuilder(
|
||||
builder: (BuildContext context, StateSetter setState) {
|
||||
return Center(
|
||||
child: RepaintBoundary(
|
||||
child: CupertinoSwitch(
|
||||
key: switchKey,
|
||||
value: value,
|
||||
dragStartBehavior: DragStartBehavior.down,
|
||||
onChanged: (bool newValue) {
|
||||
setState(() {
|
||||
value = newValue;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
final RenderObject switchRenderObject =
|
||||
tester.element(find.byType(CupertinoSwitch)).renderObject!;
|
||||
|
||||
expect(switchRenderObject, offLabelPaintPattern(alpha: 255));
|
||||
expect(switchRenderObject, onLabelPaintPattern(alpha: 0));
|
||||
|
||||
await tester.tap(find.byKey(switchKey));
|
||||
expect(value, isTrue);
|
||||
|
||||
// Kick off animation, then advance to intermediate frame.
|
||||
await tester.pump();
|
||||
await tester.pump(const Duration(milliseconds: 60));
|
||||
expect(switchRenderObject, onLabelPaintPattern(alpha: 131));
|
||||
expect(switchRenderObject, offLabelPaintPattern(alpha: 124));
|
||||
|
||||
await tester.pumpAndSettle();
|
||||
expect(switchRenderObject, onLabelPaintPattern(alpha: 255));
|
||||
expect(switchRenderObject, offLabelPaintPattern(alpha: 0));
|
||||
});
|
||||
|
||||
testWidgets('Switch renders switch labels correctly before, during, and after being tapped in high contrast', (WidgetTester tester) async {
|
||||
final Key switchKey = UniqueKey();
|
||||
bool value = false;
|
||||
await tester.pumpWidget(
|
||||
MediaQuery(
|
||||
data: const MediaQueryData(
|
||||
onOffSwitchLabels: true,
|
||||
highContrast: true,
|
||||
),
|
||||
child: Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: StatefulBuilder(
|
||||
builder: (BuildContext context, StateSetter setState) {
|
||||
return Center(
|
||||
child: RepaintBoundary(
|
||||
child: CupertinoSwitch(
|
||||
key: switchKey,
|
||||
value: value,
|
||||
dragStartBehavior: DragStartBehavior.down,
|
||||
onChanged: (bool newValue) {
|
||||
setState(() {
|
||||
value = newValue;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
final RenderObject switchRenderObject =
|
||||
tester.element(find.byType(CupertinoSwitch)).renderObject!;
|
||||
|
||||
expect(switchRenderObject, offLabelPaintPattern(highContrast: true, alpha: 255));
|
||||
expect(switchRenderObject, onLabelPaintPattern(alpha: 0));
|
||||
|
||||
await tester.tap(find.byKey(switchKey));
|
||||
expect(value, isTrue);
|
||||
|
||||
// Kick off animation, then advance to intermediate frame.
|
||||
await tester.pump();
|
||||
await tester.pump(const Duration(milliseconds: 60));
|
||||
expect(switchRenderObject, onLabelPaintPattern(alpha: 131));
|
||||
expect(switchRenderObject, offLabelPaintPattern(highContrast: true, alpha: 124));
|
||||
|
||||
await tester.pumpAndSettle();
|
||||
expect(switchRenderObject, onLabelPaintPattern(alpha: 255));
|
||||
expect(switchRenderObject, offLabelPaintPattern(highContrast: true, alpha: 0));
|
||||
});
|
||||
|
||||
testWidgets('Switch renders switch labels correctly before, during, and after being tapped with direction rtl', (WidgetTester tester) async {
|
||||
final Key switchKey = UniqueKey();
|
||||
bool value = false;
|
||||
await tester.pumpWidget(
|
||||
MediaQuery(
|
||||
data: const MediaQueryData(onOffSwitchLabels: true),
|
||||
child: Directionality(
|
||||
textDirection: TextDirection.rtl,
|
||||
child: StatefulBuilder(
|
||||
builder: (BuildContext context, StateSetter setState) {
|
||||
return Center(
|
||||
child: RepaintBoundary(
|
||||
child: CupertinoSwitch(
|
||||
key: switchKey,
|
||||
value: value,
|
||||
dragStartBehavior: DragStartBehavior.down,
|
||||
onChanged: (bool newValue) {
|
||||
setState(() {
|
||||
value = newValue;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
final RenderObject switchRenderObject =
|
||||
tester.element(find.byType(CupertinoSwitch)).renderObject!;
|
||||
|
||||
expect(switchRenderObject, offLabelPaintPattern(isRtl: true, alpha: 255));
|
||||
expect(switchRenderObject, onLabelPaintPattern(isRtl: true, alpha: 0));
|
||||
|
||||
await tester.tap(find.byKey(switchKey));
|
||||
expect(value, isTrue);
|
||||
|
||||
// Kick off animation, then advance to intermediate frame.
|
||||
await tester.pump();
|
||||
await tester.pump(const Duration(milliseconds: 60));
|
||||
expect(switchRenderObject, onLabelPaintPattern(isRtl: true, alpha: 131));
|
||||
expect(switchRenderObject, offLabelPaintPattern(isRtl: true, alpha: 124));
|
||||
|
||||
await tester.pumpAndSettle();
|
||||
expect(switchRenderObject, onLabelPaintPattern(isRtl: true, alpha: 255));
|
||||
expect(switchRenderObject, offLabelPaintPattern(isRtl: true, alpha: 0));
|
||||
});
|
||||
|
||||
testWidgets('Switch renders correctly in dark mode', (WidgetTester tester) async {
|
||||
final Key switchKey = UniqueKey();
|
||||
bool value = false;
|
||||
|
@ -154,6 +154,7 @@ void main() {
|
||||
expect(data.disableAnimations, false);
|
||||
expect(data.boldText, false);
|
||||
expect(data.highContrast, false);
|
||||
expect(data.onOffSwitchLabels, false);
|
||||
expect(data.platformBrightness, Brightness.light);
|
||||
expect(data.gestureSettings.touchSlop, null);
|
||||
expect(data.displayFeatures, isEmpty);
|
||||
@ -168,6 +169,7 @@ void main() {
|
||||
disableAnimations: true,
|
||||
boldText: true,
|
||||
highContrast: true,
|
||||
onOffSwitchLabels: true,
|
||||
alwaysUse24HourFormat: true,
|
||||
navigationMode: NavigationMode.directional,
|
||||
);
|
||||
@ -188,6 +190,7 @@ void main() {
|
||||
expect(data.disableAnimations, platformData.disableAnimations);
|
||||
expect(data.boldText, platformData.boldText);
|
||||
expect(data.highContrast, platformData.highContrast);
|
||||
expect(data.onOffSwitchLabels, platformData.onOffSwitchLabels);
|
||||
expect(data.alwaysUse24HourFormat, platformData.alwaysUse24HourFormat);
|
||||
expect(data.navigationMode, platformData.navigationMode);
|
||||
expect(data.gestureSettings, DeviceGestureSettings.fromView(tester.view));
|
||||
@ -217,6 +220,7 @@ void main() {
|
||||
expect(data.disableAnimations, tester.platformDispatcher.accessibilityFeatures.disableAnimations);
|
||||
expect(data.boldText, tester.platformDispatcher.accessibilityFeatures.boldText);
|
||||
expect(data.highContrast, tester.platformDispatcher.accessibilityFeatures.highContrast);
|
||||
expect(data.onOffSwitchLabels, tester.platformDispatcher.accessibilityFeatures.onOffSwitchLabels);
|
||||
expect(data.alwaysUse24HourFormat, tester.platformDispatcher.alwaysUse24HourFormat);
|
||||
expect(data.navigationMode, NavigationMode.traditional);
|
||||
expect(data.gestureSettings, DeviceGestureSettings.fromView(tester.view));
|
||||
@ -232,6 +236,7 @@ void main() {
|
||||
disableAnimations: true,
|
||||
boldText: true,
|
||||
highContrast: true,
|
||||
onOffSwitchLabels: true,
|
||||
alwaysUse24HourFormat: true,
|
||||
navigationMode: NavigationMode.directional,
|
||||
);
|
||||
@ -264,6 +269,7 @@ void main() {
|
||||
expect(data.disableAnimations, platformData.disableAnimations);
|
||||
expect(data.boldText, platformData.boldText);
|
||||
expect(data.highContrast, platformData.highContrast);
|
||||
expect(data.onOffSwitchLabels, platformData.onOffSwitchLabels);
|
||||
expect(data.alwaysUse24HourFormat, platformData.alwaysUse24HourFormat);
|
||||
expect(data.navigationMode, platformData.navigationMode);
|
||||
expect(data.gestureSettings, DeviceGestureSettings.fromView(tester.view));
|
||||
@ -311,6 +317,7 @@ void main() {
|
||||
expect(data.disableAnimations, tester.platformDispatcher.accessibilityFeatures.disableAnimations);
|
||||
expect(data.boldText, tester.platformDispatcher.accessibilityFeatures.boldText);
|
||||
expect(data.highContrast, tester.platformDispatcher.accessibilityFeatures.highContrast);
|
||||
expect(data.onOffSwitchLabels, tester.platformDispatcher.accessibilityFeatures.onOffSwitchLabels);
|
||||
expect(data.alwaysUse24HourFormat, tester.platformDispatcher.alwaysUse24HourFormat);
|
||||
expect(data.navigationMode, NavigationMode.traditional);
|
||||
expect(data.gestureSettings, DeviceGestureSettings.fromView(tester.view));
|
||||
@ -489,6 +496,7 @@ void main() {
|
||||
expect(copied.disableAnimations, data.disableAnimations);
|
||||
expect(copied.boldText, data.boldText);
|
||||
expect(copied.highContrast, data.highContrast);
|
||||
expect(copied.onOffSwitchLabels, data.onOffSwitchLabels);
|
||||
expect(copied.platformBrightness, data.platformBrightness);
|
||||
expect(copied.gestureSettings, data.gestureSettings);
|
||||
expect(copied.displayFeatures, data.displayFeatures);
|
||||
@ -528,6 +536,7 @@ void main() {
|
||||
disableAnimations: true,
|
||||
boldText: true,
|
||||
highContrast: true,
|
||||
onOffSwitchLabels: true,
|
||||
platformBrightness: Brightness.dark,
|
||||
navigationMode: NavigationMode.directional,
|
||||
gestureSettings: gestureSettings,
|
||||
@ -546,6 +555,7 @@ void main() {
|
||||
expect(copied.disableAnimations, true);
|
||||
expect(copied.boldText, true);
|
||||
expect(copied.highContrast, true);
|
||||
expect(copied.onOffSwitchLabels, true);
|
||||
expect(copied.platformBrightness, Brightness.dark);
|
||||
expect(copied.navigationMode, NavigationMode.directional);
|
||||
expect(copied.gestureSettings, gestureSettings);
|
||||
@ -583,6 +593,7 @@ void main() {
|
||||
disableAnimations: true,
|
||||
boldText: true,
|
||||
highContrast: true,
|
||||
onOffSwitchLabels: true,
|
||||
navigationMode: NavigationMode.directional,
|
||||
displayFeatures: displayFeatures,
|
||||
),
|
||||
@ -618,6 +629,7 @@ void main() {
|
||||
expect(unpadded.disableAnimations, true);
|
||||
expect(unpadded.boldText, true);
|
||||
expect(unpadded.highContrast, true);
|
||||
expect(unpadded.onOffSwitchLabels, true);
|
||||
expect(unpadded.navigationMode, NavigationMode.directional);
|
||||
expect(unpadded.displayFeatures, displayFeatures);
|
||||
});
|
||||
@ -653,6 +665,7 @@ void main() {
|
||||
disableAnimations: true,
|
||||
boldText: true,
|
||||
highContrast: true,
|
||||
onOffSwitchLabels: true,
|
||||
navigationMode: NavigationMode.directional,
|
||||
displayFeatures: displayFeatures,
|
||||
),
|
||||
@ -685,6 +698,7 @@ void main() {
|
||||
expect(unpadded.disableAnimations, true);
|
||||
expect(unpadded.boldText, true);
|
||||
expect(unpadded.highContrast, true);
|
||||
expect(unpadded.onOffSwitchLabels, true);
|
||||
expect(unpadded.navigationMode, NavigationMode.directional);
|
||||
expect(unpadded.displayFeatures, displayFeatures);
|
||||
});
|
||||
@ -720,6 +734,7 @@ void main() {
|
||||
disableAnimations: true,
|
||||
boldText: true,
|
||||
highContrast: true,
|
||||
onOffSwitchLabels: true,
|
||||
navigationMode: NavigationMode.directional,
|
||||
displayFeatures: displayFeatures,
|
||||
),
|
||||
@ -755,6 +770,7 @@ void main() {
|
||||
expect(unpadded.disableAnimations, true);
|
||||
expect(unpadded.boldText, true);
|
||||
expect(unpadded.highContrast, true);
|
||||
expect(unpadded.onOffSwitchLabels, true);
|
||||
expect(unpadded.navigationMode, NavigationMode.directional);
|
||||
expect(unpadded.displayFeatures, displayFeatures);
|
||||
});
|
||||
@ -790,6 +806,7 @@ void main() {
|
||||
disableAnimations: true,
|
||||
boldText: true,
|
||||
highContrast: true,
|
||||
onOffSwitchLabels: true,
|
||||
navigationMode: NavigationMode.directional,
|
||||
displayFeatures: displayFeatures,
|
||||
),
|
||||
@ -822,6 +839,7 @@ void main() {
|
||||
expect(unpadded.disableAnimations, true);
|
||||
expect(unpadded.boldText, true);
|
||||
expect(unpadded.highContrast, true);
|
||||
expect(unpadded.onOffSwitchLabels, true);
|
||||
expect(unpadded.navigationMode, NavigationMode.directional);
|
||||
expect(unpadded.displayFeatures, displayFeatures);
|
||||
});
|
||||
@ -857,6 +875,7 @@ void main() {
|
||||
disableAnimations: true,
|
||||
boldText: true,
|
||||
highContrast: true,
|
||||
onOffSwitchLabels: true,
|
||||
navigationMode: NavigationMode.directional,
|
||||
displayFeatures: displayFeatures,
|
||||
),
|
||||
@ -892,6 +911,7 @@ void main() {
|
||||
expect(unpadded.disableAnimations, true);
|
||||
expect(unpadded.boldText, true);
|
||||
expect(unpadded.highContrast, true);
|
||||
expect(unpadded.onOffSwitchLabels, true);
|
||||
expect(unpadded.navigationMode, NavigationMode.directional);
|
||||
expect(unpadded.displayFeatures, displayFeatures);
|
||||
});
|
||||
@ -927,6 +947,7 @@ void main() {
|
||||
disableAnimations: true,
|
||||
boldText: true,
|
||||
highContrast: true,
|
||||
onOffSwitchLabels: true,
|
||||
navigationMode: NavigationMode.directional,
|
||||
displayFeatures: displayFeatures,
|
||||
),
|
||||
@ -959,6 +980,7 @@ void main() {
|
||||
expect(unpadded.disableAnimations, true);
|
||||
expect(unpadded.boldText, true);
|
||||
expect(unpadded.highContrast, true);
|
||||
expect(unpadded.onOffSwitchLabels, true);
|
||||
expect(unpadded.navigationMode, NavigationMode.directional);
|
||||
expect(unpadded.displayFeatures, displayFeatures);
|
||||
});
|
||||
@ -1044,6 +1066,33 @@ void main() {
|
||||
expect(insideHighContrast, true);
|
||||
});
|
||||
|
||||
testWidgets('MediaQuery.onOffSwitchLabelsOf', (WidgetTester tester) async {
|
||||
late bool outsideOnOffSwitchLabels;
|
||||
late bool insideOnOffSwitchLabels;
|
||||
|
||||
await tester.pumpWidget(
|
||||
Builder(
|
||||
builder: (BuildContext context) {
|
||||
outsideOnOffSwitchLabels = MediaQuery.onOffSwitchLabelsOf(context);
|
||||
return MediaQuery(
|
||||
data: const MediaQueryData(
|
||||
onOffSwitchLabels: true,
|
||||
),
|
||||
child: Builder(
|
||||
builder: (BuildContext context) {
|
||||
insideOnOffSwitchLabels = MediaQuery.onOffSwitchLabelsOf(context);
|
||||
return Container();
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
expect(outsideOnOffSwitchLabels, false);
|
||||
expect(insideOnOffSwitchLabels, true);
|
||||
});
|
||||
|
||||
testWidgets('MediaQuery.boldTextOf', (WidgetTester tester) async {
|
||||
late bool outsideBoldTextOverride;
|
||||
late bool insideBoldTextOverride;
|
||||
@ -1171,6 +1220,7 @@ void main() {
|
||||
disableAnimations: true,
|
||||
boldText: true,
|
||||
highContrast: true,
|
||||
onOffSwitchLabels: true,
|
||||
displayFeatures: displayFeatures,
|
||||
),
|
||||
child: Builder(
|
||||
@ -1201,6 +1251,7 @@ void main() {
|
||||
expect(subScreenMediaQuery.disableAnimations, true);
|
||||
expect(subScreenMediaQuery.boldText, true);
|
||||
expect(subScreenMediaQuery.highContrast, true);
|
||||
expect(subScreenMediaQuery.onOffSwitchLabels, true);
|
||||
expect(subScreenMediaQuery.displayFeatures, isEmpty);
|
||||
});
|
||||
|
||||
@ -1244,6 +1295,7 @@ void main() {
|
||||
disableAnimations: true,
|
||||
boldText: true,
|
||||
highContrast: true,
|
||||
onOffSwitchLabels: true,
|
||||
displayFeatures: displayFeatures,
|
||||
),
|
||||
child: Builder(
|
||||
@ -1283,6 +1335,7 @@ void main() {
|
||||
expect(subScreenMediaQuery.disableAnimations, true);
|
||||
expect(subScreenMediaQuery.boldText, true);
|
||||
expect(subScreenMediaQuery.highContrast, true);
|
||||
expect(subScreenMediaQuery.onOffSwitchLabels, true);
|
||||
expect(subScreenMediaQuery.displayFeatures, <DisplayFeature>[cutoutDisplayFeature]);
|
||||
});
|
||||
|
||||
@ -1453,6 +1506,8 @@ void main() {
|
||||
const _MediaQueryAspectCase(MediaQuery.maybeInvertColorsOf, MediaQueryData(invertColors: true)),
|
||||
const _MediaQueryAspectCase(MediaQuery.highContrastOf, MediaQueryData(highContrast: true)),
|
||||
const _MediaQueryAspectCase(MediaQuery.maybeHighContrastOf, MediaQueryData(highContrast: true)),
|
||||
const _MediaQueryAspectCase(MediaQuery.onOffSwitchLabelsOf, MediaQueryData(onOffSwitchLabels: true)),
|
||||
const _MediaQueryAspectCase(MediaQuery.maybeOnOffSwitchLabelsOf, MediaQueryData(onOffSwitchLabels: true)),
|
||||
const _MediaQueryAspectCase(MediaQuery.disableAnimationsOf, MediaQueryData(disableAnimations: true)),
|
||||
const _MediaQueryAspectCase(MediaQuery.maybeDisableAnimationsOf, MediaQueryData(disableAnimations: true)),
|
||||
const _MediaQueryAspectCase(MediaQuery.boldTextOf, MediaQueryData(boldText: true)),
|
||||
|
Loading…
x
Reference in New Issue
Block a user