mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-04-10 22:47:58 +08:00
Allow FlatShadowNode mouting to its own view
Summary: @public This diff adds a `FlatShadowNode.forceMountToView()` method that will render its contents in it own `View`. Reviewed By: sriramramani Differential Revision: D2564502
This commit is contained in:
committed by
Ahmed El-Helw
parent
7db444c9ae
commit
8de2acd3a9
@@ -9,6 +9,12 @@
|
||||
|
||||
package com.facebook.react.flat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.facebook.react.uimanager.CatalystStylesDiffMap;
|
||||
|
||||
/**
|
||||
* Shadow node hierarchy by itself cannot display UI, it is only a representation of what UI should
|
||||
* be from JavaScript perspective. StateBuilder is a helper class that can walk the shadow node tree
|
||||
@@ -17,12 +23,21 @@ package com.facebook.react.flat;
|
||||
*/
|
||||
/* package */ final class StateBuilder {
|
||||
|
||||
private static final int[] EMPTY_INT_ARRAY = new int[0];
|
||||
|
||||
private final FlatUIViewOperationQueue mOperationsQueue;
|
||||
|
||||
private final ElementsList<DrawCommand> mDrawCommands =
|
||||
new ElementsList<>(DrawCommand.EMPTY_ARRAY);
|
||||
private final ElementsList<AttachDetachListener> mAttachDetachListeners =
|
||||
new ElementsList<>(AttachDetachListener.EMPTY_ARRAY);
|
||||
private final ElementsList<FlatShadowNode> mNativeChildren =
|
||||
new ElementsList<>(FlatShadowNode.EMPTY_ARRAY);
|
||||
|
||||
private final ArrayList<FlatShadowNode> mViewsToDetachAllChildrenFrom = new ArrayList<>();
|
||||
private final ArrayList<FlatShadowNode> mViewsToDetach = new ArrayList<>();
|
||||
|
||||
private @Nullable FlatUIViewOperationQueue.DetachAllChildrenFromViews mDetachAllChildrenFromViews;
|
||||
|
||||
/* package */ StateBuilder(FlatUIViewOperationQueue operationsQueue) {
|
||||
mOperationsQueue = operationsQueue;
|
||||
@@ -32,8 +47,24 @@ package com.facebook.react.flat;
|
||||
* Given a root of the laid-out shadow node hierarchy, walks the tree and generates an array of
|
||||
* DrawCommands that will then mount in UI thread to a root FlatViewGroup so that it can draw.
|
||||
*/
|
||||
/* package*/ void applyUpdates(FlatRootShadowNode node) {
|
||||
collectStateAndUpdateViewBounds(node, 0, 0);
|
||||
/* package */ void applyUpdates(FlatShadowNode node) {
|
||||
int tag = node.getReactTag();
|
||||
|
||||
float width = node.getLayoutWidth();
|
||||
float height = node.getLayoutHeight();
|
||||
collectStateForMountableNode(node, tag, width, height);
|
||||
|
||||
float left = node.getLayoutX();
|
||||
float top = node.getLayoutY();
|
||||
updateViewBounds(node, tag, left, top, left + width, top + height);
|
||||
|
||||
if (mDetachAllChildrenFromViews != null) {
|
||||
int[] viewsToDetachAllChildrenFrom = collectViewTags(mViewsToDetachAllChildrenFrom);
|
||||
mViewsToDetachAllChildrenFrom.clear();
|
||||
|
||||
mDetachAllChildrenFromViews.setViewsToDetachAllChildrenFrom(viewsToDetachAllChildrenFrom);
|
||||
mDetachAllChildrenFromViews = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -47,11 +78,27 @@ package com.facebook.react.flat;
|
||||
mAttachDetachListeners.add(listener);
|
||||
}
|
||||
|
||||
/* package */ void ensureBackingViewIsCreated(
|
||||
FlatShadowNode node,
|
||||
int tag,
|
||||
@Nullable CatalystStylesDiffMap styles) {
|
||||
if (node.isBackingViewCreated()) {
|
||||
return;
|
||||
}
|
||||
|
||||
mOperationsQueue.enqueueCreateView(node.getThemedContext(), tag, node.getViewClass(), styles);
|
||||
node.signalBackingViewIsCreated();
|
||||
}
|
||||
|
||||
private void addNativeChild(FlatShadowNode nativeChild) {
|
||||
mNativeChildren.add(nativeChild);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates boundaries of a View that a give nodes maps to.
|
||||
*/
|
||||
private void updateViewBounds(
|
||||
FlatRootShadowNode node,
|
||||
FlatShadowNode node,
|
||||
int tag,
|
||||
float leftInParent,
|
||||
float topInParent,
|
||||
@@ -77,12 +124,13 @@ package com.facebook.react.flat;
|
||||
* Collects state (DrawCommands) for a given node that will mount to a View.
|
||||
*/
|
||||
private void collectStateForMountableNode(
|
||||
FlatRootShadowNode node,
|
||||
FlatShadowNode node,
|
||||
int tag,
|
||||
float width,
|
||||
float height) {
|
||||
mDrawCommands.start(node.getDrawCommands());
|
||||
mAttachDetachListeners.start(node.getAttachDetachListeners());
|
||||
mNativeChildren.start(node.getNativeChildren());
|
||||
|
||||
collectStateRecursively(node, 0, 0, width, height);
|
||||
|
||||
@@ -100,8 +148,72 @@ package com.facebook.react.flat;
|
||||
}
|
||||
|
||||
if (shouldUpdateMountState) {
|
||||
mOperationsQueue.enqueueUpdateMountState(tag, drawCommands, listeners);
|
||||
mOperationsQueue.enqueueUpdateMountState(
|
||||
tag,
|
||||
drawCommands,
|
||||
listeners);
|
||||
}
|
||||
|
||||
final FlatShadowNode[] nativeChildren = mNativeChildren.finish();
|
||||
if (nativeChildren != null) {
|
||||
updateNativeChildren(node, tag, node.getNativeChildren(), nativeChildren);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateNativeChildren(
|
||||
FlatShadowNode node,
|
||||
int tag,
|
||||
FlatShadowNode[] oldNativeChildren,
|
||||
FlatShadowNode[] newNativeChildren) {
|
||||
|
||||
node.setNativeChildren(newNativeChildren);
|
||||
|
||||
if (mDetachAllChildrenFromViews == null) {
|
||||
mDetachAllChildrenFromViews = mOperationsQueue.enqueueDetachAllChildrenFromViews();
|
||||
}
|
||||
|
||||
if (oldNativeChildren.length != 0) {
|
||||
mViewsToDetachAllChildrenFrom.add(node);
|
||||
}
|
||||
|
||||
int numViewsToAdd = newNativeChildren.length;
|
||||
final int[] viewsToAdd;
|
||||
if (numViewsToAdd == 0) {
|
||||
viewsToAdd = EMPTY_INT_ARRAY;
|
||||
} else {
|
||||
viewsToAdd = new int[numViewsToAdd];
|
||||
int i = 0;
|
||||
for (FlatShadowNode child : newNativeChildren) {
|
||||
if (child.getNativeParentTag() == tag) {
|
||||
viewsToAdd[i] = -child.getReactTag();
|
||||
} else {
|
||||
viewsToAdd[i] = child.getReactTag();
|
||||
}
|
||||
// all views we add are first start detached
|
||||
child.setNativeParentTag(-1);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
// Populate an array of views to detach.
|
||||
// These views still have their native parent set as opposed to being reset to -1
|
||||
for (FlatShadowNode child : oldNativeChildren) {
|
||||
if (child.getNativeParentTag() == tag) {
|
||||
// View is attached to old parent and needs to be removed.
|
||||
mViewsToDetach.add(child);
|
||||
child.setNativeParentTag(-1);
|
||||
}
|
||||
}
|
||||
|
||||
final int[] viewsToDetach = collectViewTags(mViewsToDetach);
|
||||
mViewsToDetach.clear();
|
||||
|
||||
// restore correct parent tag
|
||||
for (FlatShadowNode child : newNativeChildren) {
|
||||
child.setNativeParentTag(tag);
|
||||
}
|
||||
|
||||
mOperationsQueue.enqueueUpdateViewGroup(tag, viewsToAdd, viewsToDetach);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -121,20 +233,15 @@ package com.facebook.react.flat;
|
||||
|
||||
for (int i = 0, childCount = node.getChildCount(); i != childCount; ++i) {
|
||||
FlatShadowNode child = (FlatShadowNode) node.getChildAt(i);
|
||||
|
||||
float childLeft = left + child.getLayoutX();
|
||||
float childTop = top + child.getLayoutY();
|
||||
float childRight = childLeft + child.getLayoutWidth();
|
||||
float childBottom = childTop + child.getLayoutHeight();
|
||||
collectStateRecursively(child, childLeft, childTop, childRight, childBottom);
|
||||
processNodeAndCollectState(child, left, top);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects state and updates View boundaries for a given root node.
|
||||
* Collects state and updates View boundaries for a given node tree.
|
||||
*/
|
||||
private void collectStateAndUpdateViewBounds(
|
||||
FlatRootShadowNode node,
|
||||
private void processNodeAndCollectState(
|
||||
FlatShadowNode node,
|
||||
float parentLeft,
|
||||
float parentTop) {
|
||||
int tag = node.getReactTag();
|
||||
@@ -147,8 +254,30 @@ package com.facebook.react.flat;
|
||||
float right = left + width;
|
||||
float bottom = top + height;
|
||||
|
||||
collectStateForMountableNode(node, tag, width, height);
|
||||
if (node.mountsToView()) {
|
||||
ensureBackingViewIsCreated(node, tag, null);
|
||||
|
||||
updateViewBounds(node, tag, left, top, right, bottom);
|
||||
addNativeChild(node);
|
||||
mDrawCommands.add(DrawView.INSTANCE);
|
||||
|
||||
collectStateForMountableNode(node, tag, width, height);
|
||||
updateViewBounds(node, tag, left, top, right, bottom);
|
||||
} else {
|
||||
collectStateRecursively(node, left, top, right, bottom);
|
||||
}
|
||||
}
|
||||
|
||||
private static int[] collectViewTags(ArrayList<FlatShadowNode> views) {
|
||||
int numViews = views.size();
|
||||
if (numViews == 0) {
|
||||
return EMPTY_INT_ARRAY;
|
||||
}
|
||||
|
||||
int[] viewTags = new int[numViews];
|
||||
for (int i = 0; i < numViews; ++i) {
|
||||
viewTags[i] = views.get(i).getReactTag();
|
||||
}
|
||||
|
||||
return viewTags;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user