diff --git a/packages/cupertino_ui/lib/src/slider.dart b/packages/cupertino_ui/lib/src/slider.dart index d047c8c5adea..d22bb60e5ddf 100644 --- a/packages/cupertino_ui/lib/src/slider.dart +++ b/packages/cupertino_ui/lib/src/slider.dart @@ -294,6 +294,8 @@ class _CupertinoSliderState extends State with TickerProviderSt Widget build(BuildContext context) { return _CupertinoSliderRenderObjectWidget( value: (widget.value - widget.min) / (widget.max - widget.min), + min: widget.min, + max: widget.max, divisions: widget.divisions, activeColor: CupertinoDynamicColor.resolve( widget.activeColor ?? CupertinoTheme.of(context).primaryColor, @@ -311,6 +313,8 @@ class _CupertinoSliderState extends State with TickerProviderSt class _CupertinoSliderRenderObjectWidget extends LeafRenderObjectWidget { const _CupertinoSliderRenderObjectWidget({ required this.value, + required this.min, + required this.max, this.divisions, required this.activeColor, required this.thumbColor, @@ -321,6 +325,8 @@ class _CupertinoSliderRenderObjectWidget extends LeafRenderObjectWidget { }); final double value; + final double min; + final double max; final int? divisions; final Color activeColor; final Color thumbColor; @@ -334,6 +340,8 @@ class _CupertinoSliderRenderObjectWidget extends LeafRenderObjectWidget { assert(debugCheckHasDirectionality(context)); return _RenderCupertinoSlider( value: value, + min: min, + max: max, divisions: divisions, activeColor: activeColor, thumbColor: CupertinoDynamicColor.resolve(thumbColor, context), @@ -352,6 +360,8 @@ class _CupertinoSliderRenderObjectWidget extends LeafRenderObjectWidget { assert(debugCheckHasDirectionality(context)); renderObject ..value = value + ..min = min + ..max = max ..divisions = divisions ..activeColor = activeColor ..thumbColor = CupertinoDynamicColor.resolve(thumbColor, context) @@ -374,18 +384,30 @@ const double _kAdjustmentUnit = 0.1; // Matches iOS implementation of material s class _RenderCupertinoSlider extends RenderConstrainedBox implements MouseTrackerAnnotation { _RenderCupertinoSlider({ - required this._value, - this._divisions, - required this._activeColor, - required this._thumbColor, - required this._trackColor, - this._onChanged, + required double value, + required double min, + required double max, + int? divisions, + required Color activeColor, + required Color thumbColor, + required Color trackColor, + _SliderValueChanged? onChanged, this.onChangeStart, this.onChangeEnd, required TickerProvider vsync, - required this._textDirection, - this._cursor = MouseCursor.defer, - }) : assert(_value >= 0.0 && _value <= 1.0), + required TextDirection textDirection, + MouseCursor cursor = MouseCursor.defer, + }) : assert(value >= 0.0 && value <= 1.0), + _value = value, + _min = min, + _max = max, + _divisions = divisions, + _activeColor = activeColor, + _thumbColor = thumbColor, + _trackColor = trackColor, + _onChanged = onChanged, + _textDirection = textDirection, + _cursor = cursor, super( additionalConstraints: const BoxConstraints.tightFor( width: _kSliderWidth, @@ -419,6 +441,26 @@ class _RenderCupertinoSlider extends RenderConstrainedBox implements MouseTracke markNeedsSemanticsUpdate(); } + double get min => _min; + double _min; + set min(double newMin) { + if (newMin == _min) { + return; + } + _min = newMin; + markNeedsSemanticsUpdate(); + } + + double get max => _max; + double _max; + set max(double newMax) { + if (newMax == _max) { + return; + } + _max = newMax; + markNeedsSemanticsUpdate(); + } + int? get divisions => _divisions; int? _divisions; set divisions(int? value) { @@ -623,11 +665,14 @@ class _RenderCupertinoSlider extends RenderConstrainedBox implements MouseTracke config.isSemanticBoundary = isInteractive; config.isSlider = true; + config.role = SemanticsRole.slider; + config.minValue = min.toString(); + config.maxValue = max.toString(); + config.value = '${(value * 100).round()}%'; if (isInteractive) { config.textDirection = textDirection; config.onIncrease = _increaseAction; config.onDecrease = _decreaseAction; - config.value = '${(value * 100).round()}%'; config.increasedValue = '${(clampDouble(value + _semanticActionUnit, 0.0, 1.0) * 100).round()}%'; config.decreasedValue = diff --git a/packages/cupertino_ui/pending_changelogs/slider_semantics_role.yaml b/packages/cupertino_ui/pending_changelogs/slider_semantics_role.yaml new file mode 100644 index 000000000000..a17478c5a49e --- /dev/null +++ b/packages/cupertino_ui/pending_changelogs/slider_semantics_role.yaml @@ -0,0 +1,3 @@ +changelog: | + - Adds `SemanticsRole.slider` and min/max value bounds to `CupertinoSlider` semantics. +version: patch diff --git a/packages/cupertino_ui/test/slider_test.dart b/packages/cupertino_ui/test/slider_test.dart index 9a8fde689003..547c4dd36c5b 100644 --- a/packages/cupertino_ui/test/slider_test.dart +++ b/packages/cupertino_ui/test/slider_test.dart @@ -442,6 +442,9 @@ void main() { tester.getSemantics(find.byType(CupertinoSlider)), matchesSemantics( isSlider: true, + role: SemanticsRole.slider, + minValue: '0.0', + maxValue: '1.0', hasIncreaseAction: true, hasDecreaseAction: true, value: '50%', @@ -462,7 +465,16 @@ void main() { ), ); - expect(tester.getSemantics(find.byType(CupertinoSlider)), matchesSemantics(isSlider: true)); + expect( + tester.getSemantics(find.byType(CupertinoSlider)), + matchesSemantics( + isSlider: true, + role: SemanticsRole.slider, + minValue: '0.0', + maxValue: '1.0', + value: '50%', + ), + ); handle.dispose(); }); @@ -483,6 +495,9 @@ void main() { tester.getSemantics(find.byType(CupertinoSlider)), matchesSemantics( isSlider: true, + role: SemanticsRole.slider, + minValue: '0.0', + maxValue: '1.0', hasIncreaseAction: true, hasDecreaseAction: true, value: '50%', @@ -506,6 +521,9 @@ void main() { tester.getSemantics(find.byType(CupertinoSlider)), matchesSemantics( isSlider: true, + role: SemanticsRole.slider, + minValue: '0.0', + maxValue: '1.0', hasIncreaseAction: true, hasDecreaseAction: true, value: '60%',