Skip to content

Commit 9b33c31

Browse files
ryancatfacebook-github-bot
authored andcommitted
Add onChildEndedNativeGesture to JSTouchDispatcher and ReactRootView to handle child gesture finishes event
Summary: Changelog: [Android][Added] Adding new API `onChildEndedNativeGesture` to the RootView interface to let its implementations notify the JS side that a child gesture is ended. Reviewed By: javache Differential Revision: D32228745 fbshipit-source-id: ad1f26546dd60f9c5a569b0bc3ad5020a01b90cc
1 parent e973b3a commit 9b33c31

File tree

5 files changed

+58
-8
lines changed

5 files changed

+58
-8
lines changed

ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java

+30-8
Original file line numberDiff line numberDiff line change
@@ -185,14 +185,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
185185

186186
@Override
187187
public void onChildStartedNativeGesture(MotionEvent ev) {
188-
if (mReactInstanceManager == null
189-
|| !mIsAttachedToInstance
190-
|| mReactInstanceManager.getCurrentReactContext() == null) {
191-
FLog.w(TAG, "Unable to dispatch touch to JS as the catalyst instance has not been attached");
192-
return;
193-
}
194-
if (mJSTouchDispatcher == null) {
195-
FLog.w(TAG, "Unable to dispatch touch to JS before the dispatcher is available");
188+
if (!isDispatcherReady()) {
196189
return;
197190
}
198191
ReactContext reactContext = mReactInstanceManager.getCurrentReactContext();
@@ -209,6 +202,35 @@ public void onChildStartedNativeGesture(View childView, MotionEvent ev) {
209202
onChildStartedNativeGesture(ev);
210203
}
211204

205+
@Override
206+
public void onChildEndedNativeGesture(View childView, MotionEvent ev) {
207+
if (!isDispatcherReady()) {
208+
return;
209+
}
210+
ReactContext reactContext = mReactInstanceManager.getCurrentReactContext();
211+
UIManager uiManager = UIManagerHelper.getUIManager(reactContext, getUIManagerType());
212+
213+
if (uiManager != null) {
214+
EventDispatcher eventDispatcher = uiManager.getEventDispatcher();
215+
mJSTouchDispatcher.onChildEndedNativeGesture(ev, eventDispatcher);
216+
}
217+
}
218+
219+
private boolean isDispatcherReady() {
220+
if (mReactInstanceManager == null
221+
|| !mIsAttachedToInstance
222+
|| mReactInstanceManager.getCurrentReactContext() == null) {
223+
FLog.w(TAG, "Unable to dispatch touch to JS as the catalyst instance has not been attached");
224+
return false;
225+
}
226+
if (mJSTouchDispatcher == null) {
227+
FLog.w(TAG, "Unable to dispatch touch to JS before the dispatcher is available");
228+
return false;
229+
}
230+
231+
return true;
232+
}
233+
212234
@Override
213235
public boolean onInterceptTouchEvent(MotionEvent ev) {
214236
dispatchJSTouchEvent(ev);

ReactAndroid/src/main/java/com/facebook/react/uimanager/JSTouchDispatcher.java

+5
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ public void onChildStartedNativeGesture(
5050
mTargetTag = -1;
5151
}
5252

53+
public void onChildEndedNativeGesture(MotionEvent androidEvent, EventDispatcher eventDispatcher) {
54+
// There should be only one child gesture at any given time. We can safely turn off the flag.
55+
mChildIsHandlingNativeGesture = false;
56+
}
57+
5358
/**
5459
* Main catalyst view is responsible for collecting and sending touch events to JS. This method
5560
* reacts for an incoming android native touch events ({@link MotionEvent}) and calls into {@link

ReactAndroid/src/main/java/com/facebook/react/uimanager/RootView.java

+6
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,11 @@ public interface RootView {
2222
/** @deprecated */
2323
void onChildStartedNativeGesture(MotionEvent ev);
2424

25+
/**
26+
* Called when a child ends a native gesture. Should be called from the child's onTouchIntercepted
27+
* implementation.
28+
*/
29+
void onChildEndedNativeGesture(View childView, MotionEvent ev);
30+
2531
void handleException(Throwable t);
2632
}

ReactAndroid/src/main/java/com/facebook/react/uimanager/events/NativeGestureUtil.java

+12
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,16 @@ public class NativeGestureUtil {
2525
public static void notifyNativeGestureStarted(View view, MotionEvent event) {
2626
RootViewUtil.getRootView(view).onChildStartedNativeGesture(view, event);
2727
}
28+
29+
/**
30+
* Helper method that should be called when a native view ends a native gesture (e.g. a native
31+
* ScrollView takes control of a gesture stream and starts scrolling). This will handle
32+
* dispatching the appropriate events to JS to make sure future gesture is not blocked.
33+
*
34+
* @param view the View ending the native gesture
35+
* @param event the MotionEvent that caused the gesture to be ended
36+
*/
37+
public static void notifyNativeGestureEnded(View view, MotionEvent event) {
38+
RootViewUtil.getRootView(view).onChildEndedNativeGesture(view, event);
39+
}
2840
}

ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.java

+5
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,11 @@ public void onChildStartedNativeGesture(View childView, MotionEvent ev) {
537537
mJSTouchDispatcher.onChildStartedNativeGesture(ev, mEventDispatcher);
538538
}
539539

540+
@Override
541+
public void onChildEndedNativeGesture(View childView, MotionEvent ev) {
542+
mJSTouchDispatcher.onChildEndedNativeGesture(ev, mEventDispatcher);
543+
}
544+
540545
@Override
541546
public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
542547
// No-op - override in order to still receive events to onInterceptTouchEvent

0 commit comments

Comments
 (0)