From 89cf5c49b96f71bf21a0373693b8d8b61c772cde Mon Sep 17 00:00:00 2001 From: Denis Koroskin Date: Mon, 7 Mar 2016 20:06:32 -0800 Subject: [PATCH] Make FlatViewGroup implement ReactCompoundViewGroup interface Summary: In FlatViewGroup, we flatten some react nodes into parent while mounting others into child Views. This is causing touch events being dispatched to wrong targets because child Views are \"stealing\" touch events from flattened Views. To fix the issue, implement ReactCompoundViewGroup to provide information about both virtual and non-virtual nodes. Reviewed By: ahmedre Differential Revision: D3018054 --- .../facebook/react/flat/FlatViewGroup.java | 31 +++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/flat/FlatViewGroup.java b/ReactAndroid/src/main/java/com/facebook/react/flat/FlatViewGroup.java index 13841bea4f..94dfd898cd 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/flat/FlatViewGroup.java +++ b/ReactAndroid/src/main/java/com/facebook/react/flat/FlatViewGroup.java @@ -29,7 +29,7 @@ import com.facebook.react.common.SystemClock; import com.facebook.react.touch.OnInterceptTouchEventListener; import com.facebook.react.touch.ReactInterceptingViewGroup; import com.facebook.react.uimanager.PointerEvents; -import com.facebook.react.uimanager.ReactCompoundView; +import com.facebook.react.uimanager.ReactCompoundViewGroup; import com.facebook.react.uimanager.ReactPointerEventsView; import com.facebook.react.uimanager.UIManagerModule; import com.facebook.react.views.image.ImageLoadEvent; @@ -39,7 +39,7 @@ import com.facebook.react.views.image.ImageLoadEvent; * array of DrawCommands, executing them one by one. */ /* package */ final class FlatViewGroup extends ViewGroup - implements ReactInterceptingViewGroup, ReactCompoundView, ReactPointerEventsView { + implements ReactInterceptingViewGroup, ReactCompoundViewGroup, ReactPointerEventsView { /** * Helper class that allows AttachDetachListener to invalidate the hosting View. */ @@ -133,6 +133,16 @@ import com.facebook.react.views.image.ImageLoadEvent; return getId(); } + @Override + public boolean interceptsTouchEvent(float touchX, float touchY) { + NodeRegion nodeRegion = anyNodeRegionWithinBounds(touchX, touchY); + if (nodeRegion != null) { + return nodeRegion.mIsVirtual; + } + + return false; + } + @Override public void dispatchDraw(Canvas canvas) { super.dispatchDraw(canvas); @@ -257,6 +267,10 @@ import com.facebook.react.views.image.ImageLoadEvent; @Override public boolean onInterceptTouchEvent(MotionEvent ev) { + if (interceptsTouchEvent(ev.getX(), ev.getY())) { + return true; + } + if (mOnInterceptTouchEventListener != null && mOnInterceptTouchEventListener.onInterceptTouchEvent(this, ev)) { return true; @@ -411,7 +425,7 @@ import com.facebook.react.views.image.ImageLoadEvent; LAYOUT_REQUESTS.clear(); } - private NodeRegion virtualNodeRegionWithinBounds(float touchX, float touchY) { + private @Nullable NodeRegion virtualNodeRegionWithinBounds(float touchX, float touchY) { for (int i = mNodeRegions.length - 1; i >= 0; --i) { NodeRegion nodeRegion = mNodeRegions[i]; if (!nodeRegion.mIsVirtual) { @@ -426,6 +440,17 @@ import com.facebook.react.views.image.ImageLoadEvent; return null; } + private @Nullable NodeRegion anyNodeRegionWithinBounds(float touchX, float touchY) { + for (int i = mNodeRegions.length - 1; i >= 0; --i) { + NodeRegion nodeRegion = mNodeRegions[i]; + if (nodeRegion.withinBounds(touchX, touchY)) { + return nodeRegion; + } + } + + return null; + } + private View ensureViewHasNoParent(View view) { ViewParent oldParent = view.getParent(); if (oldParent != null) {