diff --git a/ReactAndroid/src/main/java/com/facebook/react/flat/FlatUIImplementation.java b/ReactAndroid/src/main/java/com/facebook/react/flat/FlatUIImplementation.java index 17adb2d93..547d0031c 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/flat/FlatUIImplementation.java +++ b/ReactAndroid/src/main/java/com/facebook/react/flat/FlatUIImplementation.java @@ -16,6 +16,8 @@ import java.util.Collections; import java.util.Comparator; import java.util.List; +import com.facebook.infer.annotation.Assertions; +import com.facebook.react.bridge.Callback; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.uimanager.CatalystStylesDiffMap; @@ -151,6 +153,43 @@ public class FlatUIImplementation extends UIImplementation { addChildren(parentNode, addChildTags, addAtIndices); } + @Override + public void measure(int reactTag, Callback callback) { + FlatShadowNode node = (FlatShadowNode) resolveShadowNode(reactTag); + if (node.mountsToView()) { + super.measure(reactTag, callback); + return; + } + + float width = node.getLayoutWidth(); + float height = node.getLayoutHeight(); + + float xInParent = node.getLayoutX(); + float yInParent = node.getLayoutY(); + + while (true) { + node = Assertions.assumeNotNull((FlatShadowNode) node.getParent()); + if (node.mountsToView()) { + break; + } + + xInParent += node.getLayoutX(); + yInParent += node.getLayoutY(); + } + + float parentWidth = node.getLayoutWidth(); + float parentHeight = node.getLayoutHeight(); + + FlatUIViewOperationQueue operationsQueue = mStateBuilder.getOperationsQueue(); + operationsQueue.enqueueMeasureVirtualView( + node.getReactTag(), + xInParent / parentWidth, + yInParent / parentHeight, + width / parentWidth, + height / parentHeight, + callback); + } + /** * Removes all children defined by moveFrom and removeFrom from a given parent, * preparing elements in moveFrom to be re-added at proper index. diff --git a/ReactAndroid/src/main/java/com/facebook/react/flat/FlatUIViewOperationQueue.java b/ReactAndroid/src/main/java/com/facebook/react/flat/FlatUIViewOperationQueue.java index 7175633d6..765bde94b 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/flat/FlatUIViewOperationQueue.java +++ b/ReactAndroid/src/main/java/com/facebook/react/flat/FlatUIViewOperationQueue.java @@ -11,7 +11,9 @@ package com.facebook.react.flat; import javax.annotation.Nullable; +import com.facebook.react.bridge.Callback; import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.uimanager.PixelUtil; import com.facebook.react.uimanager.UIViewOperationQueue; /** @@ -20,6 +22,8 @@ import com.facebook.react.uimanager.UIViewOperationQueue; */ /* package */ final class FlatUIViewOperationQueue extends UIViewOperationQueue { + private static final int[] MEASURE_BUFFER = new int[4]; + private final FlatNativeViewHierarchyManager mNativeViewHierarchyManager; private final ProcessLayoutRequests mProcessLayoutRequests = new ProcessLayoutRequests(); @@ -150,6 +154,50 @@ import com.facebook.react.uimanager.UIViewOperationQueue; } } + private final class MeasureVirtualView implements UIOperation { + + private final int mReactTag; + private final float mScaledX; + private final float mScaledY; + private final float mScaledWidth; + private final float mScaledHeight; + private final Callback mCallback; + + private MeasureVirtualView( + int reactTag, + float scaledX, + float scaledY, + float scaledWidth, + float scaledHeight, + Callback callback) { + mReactTag = reactTag; + mScaledX = scaledX; + mScaledY = scaledY; + mScaledWidth = scaledWidth; + mScaledHeight = scaledHeight; + mCallback = callback; + } + + @Override + public void execute() { + // Measure native View + mNativeViewHierarchyManager.measure(mReactTag, MEASURE_BUFFER); + + float nativeViewX = MEASURE_BUFFER[0]; + float nativeViewY = MEASURE_BUFFER[1]; + float nativeViewWidth = MEASURE_BUFFER[2]; + float nativeViewHeight = MEASURE_BUFFER[3]; + + // Calculate size of the virtual child inside native View. + float x = PixelUtil.toDIPFromPixel(mScaledX * nativeViewWidth + nativeViewX); + float y = PixelUtil.toDIPFromPixel(mScaledY * nativeViewHeight + nativeViewY); + float width = PixelUtil.toDIPFromPixel(mScaledWidth * nativeViewWidth); + float height = PixelUtil.toDIPFromPixel(mScaledHeight * nativeViewHeight); + + mCallback.invoke(0, 0, width, height, x, y); + } + } + public final class DetachAllChildrenFromViews implements UIViewOperationQueue.UIOperation { private @Nullable int[] mViewsToDetachAllChildrenFrom; @@ -207,6 +255,22 @@ import com.facebook.react.uimanager.UIViewOperationQueue; enqueueUIOperation(new DropViews(viewsToDrop)); } + public void enqueueMeasureVirtualView( + int reactTag, + float scaledX, + float scaledY, + float scaledWidth, + float scaledHeight, + Callback callback) { + enqueueUIOperation(new MeasureVirtualView( + reactTag, + scaledX, + scaledY, + scaledWidth, + scaledHeight, + callback)); + } + public void enqueueProcessLayoutRequests() { enqueueUIOperation(mProcessLayoutRequests); }