mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
- Add support for "reduce motion" into AccessibilityInfo (#23839)
Summary: This PR adds `isReduceMotionEnabled()` to `AccessibilityInfo` in other to add support for "reduce motion", exposing the Operational System's settings option. Additionally, it adds a new event, `reduceMotionChanged`, in order to listen for this flag's update. With this feature, developers will be able to disable or reduce animations, _**something that will be required as soon as WCAG 2.1 draft got approved**._ See [WCAG 2.1 — 2.3.3 Animations from Interaction criteria](https://knowbility.org/blog/2018/WCAG21-233Animations/) It's exposed by [`UIAccessibility`' isReduceMotionEnabled ](https://developer.apple.com/documentation/uikit/uiaccessibility/1615133-isreducemotionenabled ) on iOS and [Settings.Global.TRANSITION_ANIMATION_SCALE](https://developer.android.com/reference/android/provider/Settings.Global#TRANSITION_ANIMATION_SCALE) on Android. Up until now, `AccessibilityInfo` only exposes screen reader flag. By adding this second accessibility option, it's a good opportunity to rename `fetch` method to an appropriate name, `isScreenReaderEnabled`, as well as rename `change` event to `screenReaderChanged`, which will make it clearer and more specific. (In case it's approved, a follow-up PR could exposes [more iOS acessibility flags](https://developer.apple.com/documentation/uikit/uiaccessibility), such as `isShakeToUndoEnabled`, `isReduceTransparencyEnabled`, `isGrayscaleEnabled`, `isInvertColorsEnabled`) (iOS code inspired by [phonegap-mobile-accessibility](https://github.com/phonegap/phonegap-mobile-accessibility). And Android by [Flutter](https://github.com/flutter/engine/blob/master/shell/platform/android/io/flutter/view/AccessibilityBridge.java )) Pull Request resolved: https://github.com/facebook/react-native/pull/23839 Differential Revision: D14406227 Pulled By: hramos fbshipit-source-id: adf43be84c488522bf1e29d862681220ad193883
This commit is contained in:
committed by
Facebook Github Bot
parent
8e490d4d87
commit
0090ab32c2
+77
-13
@@ -9,7 +9,13 @@ import javax.annotation.Nullable;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.content.ContentResolver;
|
||||
import android.database.ContentObserver;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.provider.Settings;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
|
||||
import com.facebook.react.bridge.Callback;
|
||||
@@ -36,21 +42,42 @@ public class AccessibilityInfoModule extends ReactContextBaseJavaModule
|
||||
|
||||
@Override
|
||||
public void onTouchExplorationStateChanged(boolean enabled) {
|
||||
updateAndSendChangeEvent(enabled);
|
||||
updateAndSendTouchExplorationChangeEvent(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
// Listener that is notified when the global TRANSITION_ANIMATION_SCALE.
|
||||
private final ContentObserver animationScaleObserver = new ContentObserver(new Handler(Looper.getMainLooper())) {
|
||||
@Override
|
||||
public void onChange(boolean selfChange) {
|
||||
this.onChange(selfChange, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChange(boolean selfChange, Uri uri) {
|
||||
if (getReactApplicationContext().hasActiveCatalystInstance()) {
|
||||
AccessibilityInfoModule.this.updateAndSendReduceMotionChangeEvent();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private @Nullable AccessibilityManager mAccessibilityManager;
|
||||
private @Nullable ReactTouchExplorationStateChangeListener mTouchExplorationStateChangeListener;
|
||||
private boolean mEnabled = false;
|
||||
private final ContentResolver mContentResolver;
|
||||
private boolean mReduceMotionEnabled = false;
|
||||
private boolean mTouchExplorationEnabled = false;
|
||||
|
||||
private static final String EVENT_NAME = "touchExplorationDidChange";
|
||||
private static final String REDUCE_MOTION_EVENT_NAME = "reduceMotionDidChange";
|
||||
private static final String TOUCH_EXPLORATION_EVENT_NAME = "touchExplorationDidChange";
|
||||
|
||||
public AccessibilityInfoModule(ReactApplicationContext context) {
|
||||
super(context);
|
||||
Context appContext = context.getApplicationContext();
|
||||
mAccessibilityManager = (AccessibilityManager) appContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
|
||||
mEnabled = mAccessibilityManager.isTouchExplorationEnabled();
|
||||
mContentResolver = getReactApplicationContext().getContentResolver();
|
||||
mTouchExplorationEnabled = mAccessibilityManager.isTouchExplorationEnabled();
|
||||
mReduceMotionEnabled = this.getIsReduceMotionEnabledValue();
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
mTouchExplorationStateChangeListener = new ReactTouchExplorationStateChangeListener();
|
||||
}
|
||||
@@ -61,16 +88,41 @@ public class AccessibilityInfoModule extends ReactContextBaseJavaModule
|
||||
return "AccessibilityInfo";
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void isTouchExplorationEnabled(Callback successCallback) {
|
||||
successCallback.invoke(mEnabled);
|
||||
private boolean getIsReduceMotionEnabledValue() {
|
||||
String value = Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1 ? null
|
||||
: Settings.Global.getString(
|
||||
mContentResolver,
|
||||
Settings.Global.TRANSITION_ANIMATION_SCALE
|
||||
);
|
||||
|
||||
return value != null && value.equals("0.0");
|
||||
}
|
||||
|
||||
private void updateAndSendChangeEvent(boolean enabled) {
|
||||
if (mEnabled != enabled) {
|
||||
mEnabled = enabled;
|
||||
@ReactMethod
|
||||
public void isReduceMotionEnabled(Callback successCallback) {
|
||||
successCallback.invoke(mReduceMotionEnabled);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void isTouchExplorationEnabled(Callback successCallback) {
|
||||
successCallback.invoke(mTouchExplorationEnabled);
|
||||
}
|
||||
|
||||
private void updateAndSendReduceMotionChangeEvent() {
|
||||
boolean isReduceMotionEnabled = this.getIsReduceMotionEnabledValue();
|
||||
|
||||
if (mReduceMotionEnabled != isReduceMotionEnabled) {
|
||||
mReduceMotionEnabled = isReduceMotionEnabled;
|
||||
getReactApplicationContext().getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
|
||||
.emit(EVENT_NAME, mEnabled);
|
||||
.emit(REDUCE_MOTION_EVENT_NAME, mReduceMotionEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateAndSendTouchExplorationChangeEvent(boolean enabled) {
|
||||
if (mTouchExplorationEnabled != enabled) {
|
||||
mTouchExplorationEnabled = enabled;
|
||||
getReactApplicationContext().getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
|
||||
.emit(TOUCH_EXPLORATION_EVENT_NAME, mTouchExplorationEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,7 +132,14 @@ public class AccessibilityInfoModule extends ReactContextBaseJavaModule
|
||||
mAccessibilityManager.addTouchExplorationStateChangeListener(
|
||||
mTouchExplorationStateChangeListener);
|
||||
}
|
||||
updateAndSendChangeEvent(mAccessibilityManager.isTouchExplorationEnabled());
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
Uri transitionUri = Settings.Global.getUriFor(Settings.Global.TRANSITION_ANIMATION_SCALE);
|
||||
mContentResolver.registerContentObserver(transitionUri, false, animationScaleObserver);
|
||||
}
|
||||
|
||||
updateAndSendTouchExplorationChangeEvent(mAccessibilityManager.isTouchExplorationEnabled());
|
||||
updateAndSendReduceMotionChangeEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -89,12 +148,17 @@ public class AccessibilityInfoModule extends ReactContextBaseJavaModule
|
||||
mAccessibilityManager.removeTouchExplorationStateChangeListener(
|
||||
mTouchExplorationStateChangeListener);
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
mContentResolver.unregisterContentObserver(animationScaleObserver);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
getReactApplicationContext().addLifecycleEventListener(this);
|
||||
updateAndSendChangeEvent(mAccessibilityManager.isTouchExplorationEnabled());
|
||||
updateAndSendTouchExplorationChangeEvent(mAccessibilityManager.isTouchExplorationEnabled());
|
||||
updateAndSendReduceMotionChangeEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user