diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java b/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java index 9d6d1bfd1..99c23d7af 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java @@ -142,7 +142,7 @@ public class ReactRootView extends SizeMonitoringFrameLayout implements RootView // {@link #findTargetTagForTouch} to find react view ID that will be responsible for handling // this gesture mChildIsHandlingNativeGesture = false; - mTargetTag = TouchTargetHelper.findTargetTagForTouch(ev.getRawY(), ev.getRawX(), this); + mTargetTag = TouchTargetHelper.findTargetTagForTouch(ev.getY(), ev.getX(), this); eventDispatcher.dispatchEvent(new TouchEvent(mTargetTag, TouchEventType.START, ev)); } else if (mChildIsHandlingNativeGesture) { // If the touch was intercepted by a child, we've already sent a cancel event to JS for this diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/TouchTargetHelper.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/TouchTargetHelper.java index 0902c8dd9..6826bc663 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/TouchTargetHelper.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/TouchTargetHelper.java @@ -79,17 +79,27 @@ public class TouchTargetHelper { // parent, therefore `getGlobalVisibleRect` call will return bogus result as it treat view // with no parent as a root of the view hierarchy. To prevent this from happening we check // that view has a parent before visiting it. - if (child.getParent() != null && child.getGlobalVisibleRect(mVisibleRect)) { - if (eventX >= mVisibleRect.left && eventX <= mVisibleRect.right - && eventY >= mVisibleRect.top && eventY <= mVisibleRect.bottom) { - View targetView = findTouchTargetViewWithPointerEvents(eventX, eventY, child); - if (targetView != null) { - return targetView; - } + if (child.getParent() != null && isTouchPointInView(eventX, eventY, viewGroup, child)) { + // Apply offset to event coordinates to transform them into the coordinate space of the + // child view, taken from {@link ViewGroup#dispatchTransformedTouchEvent()}. + eventX += viewGroup.getScrollX() - child.getLeft(); + eventY += viewGroup.getScrollY() - child.getTop(); + View targetView = findTouchTargetViewWithPointerEvents(eventX, eventY, child); + if (targetView != null) { + return targetView; } } } return viewGroup; +} + + // Taken from {@link ViewGroup#isTransformedTouchPointInView()} + private static boolean isTouchPointInView(float x, float y, ViewGroup parent, View child) { + float localX = x + parent.getScrollX() - child.getLeft(); + float localY = y + parent.getScrollY() - child.getTop(); + // Taken from {@link View#pointInView()}. + return localX >= 0 && localX < (child.getRight() - child.getLeft()) + && localY >= 0 && localY < (child.getBottom() - child.getTop()); } /** diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIViewOperationQueue.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIViewOperationQueue.java index 001cf080d..614f67df4 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIViewOperationQueue.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIViewOperationQueue.java @@ -385,8 +385,8 @@ public class UIViewOperationQueue { final int touchTargetReactTag = mNativeViewHierarchyManager.findTargetTagForTouch( mReactTag, - mTargetX + containerX, - mTargetY + containerY); + mTargetX, + mTargetY); try { mNativeViewHierarchyManager.measure(