diff --git a/ReactAndroid/src/main/java/com/facebook/react/flat/FlatShadowNode.java b/ReactAndroid/src/main/java/com/facebook/react/flat/FlatShadowNode.java index fe635de33f6..a8c7d6a4c25 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/flat/FlatShadowNode.java +++ b/ReactAndroid/src/main/java/com/facebook/react/flat/FlatShadowNode.java @@ -251,10 +251,15 @@ import com.facebook.react.uimanager.annotations.ReactProp; mNodeRegions = nodeRegion; } - /* package */ void updateNodeRegion(float left, float top, float right, float bottom) { - if (mNodeRegion.mLeft != left || mNodeRegion.mTop != top || - mNodeRegion.mRight != right || mNodeRegion.mBottom != bottom) { - setNodeRegion(new NodeRegion(left, top, right, bottom, getReactTag())); + /* package */ void updateNodeRegion( + float left, + float top, + float right, + float bottom, + boolean isVirtual) { + if (mNodeRegion.mLeft != left || mNodeRegion.mTop != top || mNodeRegion.mRight != right || + mNodeRegion.mBottom != bottom || mNodeRegion.mIsVirtual != isVirtual) { + setNodeRegion(new NodeRegion(left, top, right, bottom, getReactTag(), isVirtual)); } } 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 5e2a2385fe8..13841bea4f4 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/flat/FlatViewGroup.java +++ b/ReactAndroid/src/main/java/com/facebook/react/flat/FlatViewGroup.java @@ -123,7 +123,7 @@ import com.facebook.react.views.image.ImageLoadEvent; "TouchTargetHelper should not allow calling this method when pointer events are NONE"); if (mPointerEvents != PointerEvents.BOX_ONLY) { - NodeRegion nodeRegion = nodeRegionWithinBounds(touchX, touchY); + NodeRegion nodeRegion = virtualNodeRegionWithinBounds(touchX, touchY); if (nodeRegion != null) { return nodeRegion.getReactTag(touchX, touchY); } @@ -277,7 +277,7 @@ import com.facebook.react.views.image.ImageLoadEvent; if (mPointerEvents == PointerEvents.BOX_NONE) { // We cannot always return false here because some child nodes could be flatten into this View - NodeRegion nodeRegion = nodeRegionWithinBounds(ev.getX(), ev.getY()); + NodeRegion nodeRegion = virtualNodeRegionWithinBounds(ev.getX(), ev.getY()); if (nodeRegion == null) { // no child to handle this touch event, bailing out. return false; @@ -411,9 +411,13 @@ import com.facebook.react.views.image.ImageLoadEvent; LAYOUT_REQUESTS.clear(); } - private NodeRegion nodeRegionWithinBounds(float touchX, float touchY) { + private NodeRegion virtualNodeRegionWithinBounds(float touchX, float touchY) { for (int i = mNodeRegions.length - 1; i >= 0; --i) { NodeRegion nodeRegion = mNodeRegions[i]; + if (!nodeRegion.mIsVirtual) { + // only interested in virtual nodes + continue; + } if (nodeRegion.withinBounds(touchX, touchY)) { return nodeRegion; } diff --git a/ReactAndroid/src/main/java/com/facebook/react/flat/NodeRegion.java b/ReactAndroid/src/main/java/com/facebook/react/flat/NodeRegion.java index db4f8109bb6..41f72549f5c 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/flat/NodeRegion.java +++ b/ReactAndroid/src/main/java/com/facebook/react/flat/NodeRegion.java @@ -11,20 +11,28 @@ package com.facebook.react.flat; /* package */ class NodeRegion { /* package */ static final NodeRegion[] EMPTY_ARRAY = new NodeRegion[0]; - /* package */ static final NodeRegion EMPTY = new NodeRegion(0, 0, 0, 0, -1); + /* package */ static final NodeRegion EMPTY = new NodeRegion(0, 0, 0, 0, -1, false); /* package */ final float mLeft; /* package */ final float mTop; /* package */ final float mRight; /* package */ final float mBottom; /* package */ final int mTag; + /* package */ final boolean mIsVirtual; - /* package */ NodeRegion(float left, float top, float right, float bottom, int tag) { + /* package */ NodeRegion( + float left, + float top, + float right, + float bottom, + int tag, + boolean isVirtual) { mLeft = left; mTop = top; mRight = right; mBottom = bottom; mTag = tag; + mIsVirtual = isVirtual; } /* package */ final boolean withinBounds(float touchX, float touchY) { diff --git a/ReactAndroid/src/main/java/com/facebook/react/flat/RCTText.java b/ReactAndroid/src/main/java/com/facebook/react/flat/RCTText.java index e2b98d23307..b216dda308b 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/flat/RCTText.java +++ b/ReactAndroid/src/main/java/com/facebook/react/flat/RCTText.java @@ -223,9 +223,14 @@ import com.facebook.react.uimanager.annotations.ReactProp; } @Override - /* package */ void updateNodeRegion(float left, float top, float right, float bottom) { + /* package */ void updateNodeRegion( + float left, + float top, + float right, + float bottom, + boolean isVirtual) { if (mDrawCommand == null) { - super.updateNodeRegion(left, top, right, bottom); + super.updateNodeRegion(left, top, right, bottom, isVirtual); return; } @@ -239,8 +244,9 @@ import com.facebook.react.uimanager.annotations.ReactProp; Layout newLayout = mDrawCommand.getLayout(); if (nodeRegion.mLeft != left || nodeRegion.mTop != top || nodeRegion.mRight != right || nodeRegion.mBottom != bottom || - layout != newLayout) { - setNodeRegion(new TextNodeRegion(left, top, right, bottom, getReactTag(), newLayout)); + nodeRegion.mIsVirtual != isVirtual || layout != newLayout) { + setNodeRegion( + new TextNodeRegion(left, top, right, bottom, getReactTag(), isVirtual, newLayout)); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/flat/StateBuilder.java b/ReactAndroid/src/main/java/com/facebook/react/flat/StateBuilder.java index e5be9c10b1d..f2cc1b046ce 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/flat/StateBuilder.java +++ b/ReactAndroid/src/main/java/com/facebook/react/flat/StateBuilder.java @@ -197,13 +197,14 @@ import com.facebook.react.uimanager.events.EventDispatcher; float left, float top, float right, - float bottom) { + float bottom, + boolean isVirtual) { if (left == right || top == bottom) { // no point in adding an empty NodeRegion return; } - node.updateNodeRegion(left, top, right, bottom); + node.updateNodeRegion(left, top, right, bottom, isVirtual); mNodeRegions.add(node.getNodeRegion()); } @@ -291,7 +292,7 @@ import com.facebook.react.uimanager.events.EventDispatcher; // FlatViewGroup.reactTagForTouch() will always return RCTText's id. To fix the issue, // manually add nodeRegion so it will have exactly one NodeRegion, and virtual nodes will // be able to receive touch events. - addNodeRegion(node, left, top, right, bottom); + addNodeRegion(node, left, top, right, bottom, true); } boolean descendantUpdated = collectStateRecursively( @@ -520,9 +521,15 @@ import com.facebook.react.uimanager.events.EventDispatcher; float right = left + width; float bottom = top + height; + boolean mountsToView = node.mountsToView(); + final boolean updated; - if (node.mountsToView()) { + if (!parentIsAndroidView) { + addNodeRegion(node, left, top, right, bottom, !mountsToView); + } + + if (mountsToView) { ensureBackingViewIsCreated(node); addNativeChild(node); @@ -549,8 +556,6 @@ import com.facebook.react.uimanager.events.EventDispatcher; updateViewBounds(node, left, top, right, bottom); } } else { - addNodeRegion(node, left, top, right, bottom); - updated = collectStateRecursively( node, left, diff --git a/ReactAndroid/src/main/java/com/facebook/react/flat/TextNodeRegion.java b/ReactAndroid/src/main/java/com/facebook/react/flat/TextNodeRegion.java index e6d4894589b..ab2290d534b 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/flat/TextNodeRegion.java +++ b/ReactAndroid/src/main/java/com/facebook/react/flat/TextNodeRegion.java @@ -15,8 +15,15 @@ import android.text.Spanned; /* package */ final class TextNodeRegion extends NodeRegion { private final Layout mLayout; - TextNodeRegion(float left, float top, float right, float bottom, int tag, Layout layout) { - super(left, top, right, bottom, tag); + /* package */ TextNodeRegion( + float left, + float top, + float right, + float bottom, + int tag, + boolean isVirtual, + Layout layout) { + super(left, top, right, bottom, tag, isVirtual); mLayout = layout; }