9
9
10
10
import android .annotation .TargetApi ;
11
11
import android .content .Context ;
12
+ import android .content .ContentResolver ;
13
+ import android .database .ContentObserver ;
14
+ import android .net .Uri ;
12
15
import android .os .Build ;
16
+ import android .os .Handler ;
17
+ import android .os .Looper ;
18
+ import android .provider .Settings ;
13
19
import android .view .accessibility .AccessibilityManager ;
14
20
15
21
import com .facebook .react .bridge .Callback ;
@@ -36,21 +42,42 @@ private class ReactTouchExplorationStateChangeListener
36
42
37
43
@ Override
38
44
public void onTouchExplorationStateChanged (boolean enabled ) {
39
- updateAndSendChangeEvent (enabled );
45
+ updateAndSendTouchExplorationChangeEvent (enabled );
40
46
}
41
47
}
42
48
49
+ // Listener that is notified when the global TRANSITION_ANIMATION_SCALE.
50
+ private final ContentObserver animationScaleObserver = new ContentObserver (new Handler (Looper .getMainLooper ())) {
51
+ @ Override
52
+ public void onChange (boolean selfChange ) {
53
+ this .onChange (selfChange , null );
54
+ }
55
+
56
+ @ Override
57
+ public void onChange (boolean selfChange , Uri uri ) {
58
+ if (getReactApplicationContext ().hasActiveCatalystInstance ()) {
59
+ AccessibilityInfoModule .this .updateAndSendReduceMotionChangeEvent ();
60
+ }
61
+ }
62
+ };
63
+
43
64
private @ Nullable AccessibilityManager mAccessibilityManager ;
44
65
private @ Nullable ReactTouchExplorationStateChangeListener mTouchExplorationStateChangeListener ;
45
- private boolean mEnabled = false ;
66
+ private final ContentResolver mContentResolver ;
67
+ private boolean mReduceMotionEnabled = false ;
68
+ private boolean mTouchExplorationEnabled = false ;
46
69
47
- private static final String EVENT_NAME = "touchExplorationDidChange" ;
70
+ private static final String REDUCE_MOTION_EVENT_NAME = "reduceMotionDidChange" ;
71
+ private static final String TOUCH_EXPLORATION_EVENT_NAME = "touchExplorationDidChange" ;
48
72
49
73
public AccessibilityInfoModule (ReactApplicationContext context ) {
50
74
super (context );
51
75
Context appContext = context .getApplicationContext ();
52
76
mAccessibilityManager = (AccessibilityManager ) appContext .getSystemService (Context .ACCESSIBILITY_SERVICE );
53
- mEnabled = mAccessibilityManager .isTouchExplorationEnabled ();
77
+ mContentResolver = getReactApplicationContext ().getContentResolver ();
78
+ mTouchExplorationEnabled = mAccessibilityManager .isTouchExplorationEnabled ();
79
+ mReduceMotionEnabled = this .getIsReduceMotionEnabledValue ();
80
+
54
81
if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .KITKAT ) {
55
82
mTouchExplorationStateChangeListener = new ReactTouchExplorationStateChangeListener ();
56
83
}
@@ -61,16 +88,41 @@ public String getName() {
61
88
return "AccessibilityInfo" ;
62
89
}
63
90
91
+ private boolean getIsReduceMotionEnabledValue () {
92
+ String value = Build .VERSION .SDK_INT < Build .VERSION_CODES .JELLY_BEAN_MR1 ? null
93
+ : Settings .Global .getString (
94
+ mContentResolver ,
95
+ Settings .Global .TRANSITION_ANIMATION_SCALE
96
+ );
97
+
98
+ return value != null && value .equals ("0.0" );
99
+ }
100
+
101
+ @ ReactMethod
102
+ public void isReduceMotionEnabled (Callback successCallback ) {
103
+ successCallback .invoke (mReduceMotionEnabled );
104
+ }
105
+
64
106
@ ReactMethod
65
107
public void isTouchExplorationEnabled (Callback successCallback ) {
66
- successCallback .invoke (mEnabled );
108
+ successCallback .invoke (mTouchExplorationEnabled );
109
+ }
110
+
111
+ private void updateAndSendReduceMotionChangeEvent () {
112
+ boolean isReduceMotionEnabled = this .getIsReduceMotionEnabledValue ();
113
+
114
+ if (mReduceMotionEnabled != isReduceMotionEnabled ) {
115
+ mReduceMotionEnabled = isReduceMotionEnabled ;
116
+ getReactApplicationContext ().getJSModule (DeviceEventManagerModule .RCTDeviceEventEmitter .class )
117
+ .emit (REDUCE_MOTION_EVENT_NAME , mReduceMotionEnabled );
118
+ }
67
119
}
68
120
69
- private void updateAndSendChangeEvent (boolean enabled ) {
70
- if (mEnabled != enabled ) {
71
- mEnabled = enabled ;
121
+ private void updateAndSendTouchExplorationChangeEvent (boolean enabled ) {
122
+ if (mTouchExplorationEnabled != enabled ) {
123
+ mTouchExplorationEnabled = enabled ;
72
124
getReactApplicationContext ().getJSModule (DeviceEventManagerModule .RCTDeviceEventEmitter .class )
73
- .emit (EVENT_NAME , mEnabled );
125
+ .emit (TOUCH_EXPLORATION_EVENT_NAME , mTouchExplorationEnabled );
74
126
}
75
127
}
76
128
@@ -80,7 +132,14 @@ public void onHostResume() {
80
132
mAccessibilityManager .addTouchExplorationStateChangeListener (
81
133
mTouchExplorationStateChangeListener );
82
134
}
83
- updateAndSendChangeEvent (mAccessibilityManager .isTouchExplorationEnabled ());
135
+
136
+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .JELLY_BEAN_MR1 ) {
137
+ Uri transitionUri = Settings .Global .getUriFor (Settings .Global .TRANSITION_ANIMATION_SCALE );
138
+ mContentResolver .registerContentObserver (transitionUri , false , animationScaleObserver );
139
+ }
140
+
141
+ updateAndSendTouchExplorationChangeEvent (mAccessibilityManager .isTouchExplorationEnabled ());
142
+ updateAndSendReduceMotionChangeEvent ();
84
143
}
85
144
86
145
@ Override
@@ -89,12 +148,17 @@ public void onHostPause() {
89
148
mAccessibilityManager .removeTouchExplorationStateChangeListener (
90
149
mTouchExplorationStateChangeListener );
91
150
}
151
+
152
+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .JELLY_BEAN_MR1 ) {
153
+ mContentResolver .unregisterContentObserver (animationScaleObserver );
154
+ }
92
155
}
93
156
94
157
@ Override
95
158
public void initialize () {
96
159
getReactApplicationContext ().addLifecycleEventListener (this );
97
- updateAndSendChangeEvent (mAccessibilityManager .isTouchExplorationEnabled ());
160
+ updateAndSendTouchExplorationChangeEvent (mAccessibilityManager .isTouchExplorationEnabled ());
161
+ updateAndSendReduceMotionChangeEvent ();
98
162
}
99
163
100
164
@ Override
0 commit comments