Make FlatUIImplementation.measure() work with virtual views (shadow nodes that don't map to a View)

Summary: UIImplementation.measure() can only measure shadow nodes that map to native Views. As a result of this, every time we tried to measure a shadow node that doesn't map to a View, we trigger callback with no data (to indicate an error). To fix this issue, walk up until we find a node that maps to a View, then measure that View and adjust for the bounds of a virtual child.

Reviewed By: ahmedre

Differential Revision: D2800960
This commit is contained in:
Denis Koroskin
2016-12-19 13:40:19 -08:00
committed by Ahmed El-Helw
parent b321ea98d3
commit 05544f6bca
2 changed files with 103 additions and 0 deletions
@@ -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);
}