Fix accessibilityIncrement for discrete sliders
When numberOfDiscreteValues is non-zero, the MDCSlider should use these as the step value in accessibilityIncrement and accessibilityDecrement. If the number of discrete values is fewer than 8, then VoiceOver users cannot modify the slider value by swiping up or down.
MODIFY
components/Slider/src/MDCSlider.m
components/Slider/src/MDCSlider.m
@@ -445,7 +445,11 @@ static inline UIColor *MDCThumbTrackDefaultColor(void) {
- (void)accessibilityIncrement {
if (self.enabled) {
CGFloat range = self.maximumValue - self.minimumValue;
- CGFloat newValue = self.value + kSliderAccessibilityIncrement * range;
+ CGFloat adjustmentAmount = kSliderAccessibilityIncrement * range;
+ if (self.numberOfDiscreteValues > 1) {
+ adjustmentAmount = range / (self.numberOfDiscreteValues - 1);
+ }
+ CGFloat newValue = self.value + adjustmentAmount;
[_thumbTrack setValue:newValue
animated:NO
animateThumbAfterMove:NO
@@ -459,7 +463,11 @@ static inline UIColor *MDCThumbTrackDefaultColor(void) {
- (void)accessibilityDecrement {
if (self.enabled) {
CGFloat range = self.maximumValue - self.minimumValue;
- CGFloat newValue = self.value - kSliderAccessibilityIncrement * range;
+ CGFloat adjustmentAmount = kSliderAccessibilityIncrement * range;
+ if (self.numberOfDiscreteValues > 1) {
+ adjustmentAmount = range / (self.numberOfDiscreteValues - 1);
+ }
+ CGFloat newValue = self.value - adjustmentAmount;
[_thumbTrack setValue:newValue
animated:NO
animateThumbAfterMove:NO

MODIFY
components/Slider/tests/unit/SliderTests.m
components/Slider/tests/unit/SliderTests.m
@@ -1069,6 +1069,27 @@ static const CGFloat kEpsilonAccuracy = 0.001f;
XCTAssertTrue(self.slider.accessibilityTraits & UIAccessibilityTraitAdjustable);
}
+- (void)testAccessibilityIncrementDiscreteSlider {
+ for (NSUInteger i = 2; i < 20; ++i) {
+ // Given
+ self.slider.numberOfDiscreteValues = i;
+ self.slider.minimumValue = 0;
+ self.slider.maximumValue = 1;
+ self.slider.value = self.slider.minimumValue;
+
+ // When
+ [self.slider accessibilityIncrement];
+
+ // Then
+ CGFloat stepValue = (self.slider.maximumValue - self.slider.minimumValue) /
+ (self.slider.numberOfDiscreteValues - 1);
+ CGFloat expectedValue = self.slider.minimumValue + stepValue;
+ XCTAssertEqualWithAccuracy(self.slider.value, expectedValue, 0.0001,
+ @"A slider with (%lu) discrete values should have step of '%.3f'.",
+ (unsigned long)self.slider.numberOfDiscreteValues, stepValue);
+ }
+}
+
#pragma mark Private test helpers
- (CGFloat)randomNumber {

Fix accessibilityIncrement for discrete sliders (#4327)

When numberOfDiscreteValues is non-zero, the MDCSlider should use these as the step value in accessibilityIncrement and accessibilityDecrement. If the number of discrete values is fewer than 8, then VoiceOver users cannot modify the slider value by swiping up or down.