diff --git a/React/Views/RCTSlider.m b/React/Views/RCTSlider.m index 11898a82fa426b..5b45c76c7cf437 100644 --- a/React/Views/RCTSlider.m +++ b/React/Views/RCTSlider.m @@ -84,4 +84,24 @@ - (UIImage *)thumbImage return [self thumbImageForState:UIControlStateNormal]; } +- (void)accessibilityIncrement +{ + [super accessibilityIncrement]; + if (_onSlidingComplete) { + _onSlidingComplete(@{ + @"value": @(self.value), + }); + } +} + +- (void)accessibilityDecrement +{ + [super accessibilityDecrement]; + if (_onSlidingComplete) { + _onSlidingComplete(@{ + @"value": @(self.value), + }); + } +} + @end diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/slider/ReactSliderManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/slider/ReactSliderManager.java index 1b31adfdaad6f0..7f20cb03cd9267 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/slider/ReactSliderManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/slider/ReactSliderManager.java @@ -10,10 +10,14 @@ import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.graphics.drawable.LayerDrawable; +import android.os.Bundle; import android.view.View; import android.view.ViewGroup; import android.widget.SeekBar; import androidx.annotation.Nullable; +import androidx.core.view.AccessibilityDelegateCompat; +import androidx.core.view.ViewCompat; +import androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat; import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.common.MapBuilder; @@ -132,7 +136,9 @@ public Class getShadowNodeClass() { @Override protected ReactSlider createViewInstance(ThemedReactContext context) { - return new ReactSlider(context, null, STYLE); + final ReactSlider slider = new ReactSlider(context, null, STYLE); + ViewCompat.setAccessibilityDelegate(slider, sAccessibilityDelegate); + return slider; } @Override @@ -256,4 +262,27 @@ public long measure( protected ViewManagerDelegate getDelegate() { return mDelegate; } + + protected static class ReactSliderAccessibilityDelegate extends AccessibilityDelegateCompat { + private static boolean isSliderAction(int action) { + return (action == AccessibilityActionCompat.ACTION_SCROLL_FORWARD.getId()) + || (action == AccessibilityActionCompat.ACTION_SCROLL_BACKWARD.getId()) + || (action == AccessibilityActionCompat.ACTION_SET_PROGRESS.getId()); + } + + @Override + public boolean performAccessibilityAction(View host, int action, Bundle args) { + if (isSliderAction(action)) { + ON_CHANGE_LISTENER.onStartTrackingTouch((SeekBar) host); + } + final boolean rv = super.performAccessibilityAction(host, action, args); + if (isSliderAction(action)) { + ON_CHANGE_LISTENER.onStopTrackingTouch((SeekBar) host); + } + return rv; + } + }; + + protected static ReactSliderAccessibilityDelegate sAccessibilityDelegate = + new ReactSliderAccessibilityDelegate(); }