Add support for dynamically sized ReactRootView

Reviewed By: achen1, AaaChiuuu

Differential Revision: D5745093

fbshipit-source-id: 65d85252ab8a0ca38322f49a3d4812380d5228c4
This commit is contained in:
David Vacca
2017-09-08 21:07:13 -07:00
committed by Facebook Github Bot
parent 1afc93d18a
commit 4ca617211b
5 changed files with 245 additions and 64 deletions

View File

@@ -8,7 +8,12 @@
*/
package com.facebook.react.uimanager;
import static android.view.View.MeasureSpec.AT_MOST;
import static android.view.View.MeasureSpec.EXACTLY;
import static android.view.View.MeasureSpec.UNSPECIFIED;
import android.os.SystemClock;
import android.view.View.MeasureSpec;
import com.facebook.common.logging.FLog;
import com.facebook.infer.annotation.Assertions;
import com.facebook.react.animation.Animation;
@@ -27,8 +32,10 @@ import com.facebook.systrace.Systrace;
import com.facebook.systrace.SystraceMessage;
import com.facebook.yoga.YogaDirection;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
/**
@@ -37,6 +44,7 @@ import javax.annotation.Nullable;
*/
public class UIImplementation {
private final Set<Integer> mMeasuredRootNodes = new HashSet<>();
private final ShadowNodeRegistry mShadowNodeRegistry = new ShadowNodeRegistry();
private final ViewManagerRegistry mViewManagers;
private final UIViewOperationQueue mOperationsQueue;
@@ -116,20 +124,66 @@ public class UIImplementation {
}
/**
* Registers a root node with a given tag, size and ThemedReactContext
* and adds it to a node registry.
* Updates the styles of the {@link ReactShadowNode} based on the Measure specs received by
* parameters.
*/
public void registerRootView(
SizeMonitoringFrameLayout rootView,
int tag,
int width,
int height,
ThemedReactContext context) {
public void updateRootView(int tag, int widthMeasureSpec, int heightMeasureSpec) {
ReactShadowNode rootCSSNode = mShadowNodeRegistry.getNode(tag);
if (rootCSSNode == null) {
FLog.w(ReactConstants.TAG, "Tried to update non-existent root tag: " + tag);
return;
}
updateRootView(rootCSSNode, widthMeasureSpec, heightMeasureSpec);
}
/**
* Updates the styles of the {@link ReactShadowNode} based on the Measure specs received by
* parameters.
*/
public void updateRootView(
ReactShadowNode rootCSSNode, int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
switch (widthMode) {
case EXACTLY:
rootCSSNode.setStyleWidth(widthSize);
break;
case AT_MOST:
rootCSSNode.setStyleMaxWidth(widthSize);
break;
case UNSPECIFIED:
rootCSSNode.setStyleWidthAuto();
break;
}
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
switch (heightMode) {
case EXACTLY:
rootCSSNode.setStyleHeight(heightSize);
break;
case AT_MOST:
rootCSSNode.setStyleMaxHeight(heightSize);
break;
case UNSPECIFIED:
rootCSSNode.setStyleHeightAuto();
break;
}
}
/**
* Registers a root node with a given tag, size and ThemedReactContext and adds it to a node
* registry.
*/
public <T extends SizeMonitoringFrameLayout & MeasureSpecProvider> void registerRootView(
T rootView, int tag, ThemedReactContext context) {
final ReactShadowNode rootCSSNode = createRootShadowNode();
rootCSSNode.setReactTag(tag);
rootCSSNode.setThemedContext(context);
rootCSSNode.setStyleWidth(width);
rootCSSNode.setStyleHeight(height);
int widthMeasureSpec = rootView.getWidthMeasureSpec();
int heightMeasureSpec = rootView.getHeightMeasureSpec();
updateRootView(rootCSSNode, widthMeasureSpec, heightMeasureSpec);
mShadowNodeRegistry.addRootNode(rootCSSNode);
@@ -583,27 +637,29 @@ public class UIImplementation {
for (int i = 0; i < mShadowNodeRegistry.getRootNodeCount(); i++) {
int tag = mShadowNodeRegistry.getRootTag(i);
ReactShadowNode cssRoot = mShadowNodeRegistry.getNode(tag);
SystraceMessage.beginSection(
Systrace.TRACE_TAG_REACT_JAVA_BRIDGE,
"UIImplementation.notifyOnBeforeLayoutRecursive")
.arg("rootTag", cssRoot.getReactTag())
.flush();
try {
notifyOnBeforeLayoutRecursive(cssRoot);
} finally {
Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);
}
calculateRootLayout(cssRoot);
SystraceMessage.beginSection(
Systrace.TRACE_TAG_REACT_JAVA_BRIDGE,
"UIImplementation.applyUpdatesRecursive")
.arg("rootTag", cssRoot.getReactTag())
.flush();
try {
applyUpdatesRecursive(cssRoot, 0f, 0f);
} finally {
Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);
if (mMeasuredRootNodes.contains(tag)) {
SystraceMessage.beginSection(
Systrace.TRACE_TAG_REACT_JAVA_BRIDGE,
"UIImplementation.notifyOnBeforeLayoutRecursive")
.arg("rootTag", cssRoot.getReactTag())
.flush();
try {
notifyOnBeforeLayoutRecursive(cssRoot);
} finally {
Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);
}
calculateRootLayout(cssRoot);
SystraceMessage.beginSection(
Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "UIImplementation.applyUpdatesRecursive")
.arg("rootTag", cssRoot.getReactTag())
.flush();
try {
applyUpdatesRecursive(cssRoot, 0f, 0f);
} finally {
Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);
}
}
}
} finally {
@@ -729,6 +785,7 @@ public class UIImplementation {
private void removeShadowNodeRecursive(ReactShadowNode nodeToRemove) {
NativeViewHierarchyOptimizer.handleRemoveNode(nodeToRemove);
mShadowNodeRegistry.removeNode(nodeToRemove.getReactTag());
mMeasuredRootNodes.remove(nodeToRemove.getReactTag());
for (int i = nodeToRemove.getChildCount() - 1; i >= 0; i--) {
removeShadowNodeRecursive(nodeToRemove.getChildAt(i));
}
@@ -906,4 +963,13 @@ public class UIImplementation {
return rootTag;
}
/**
* Enables Layout calculation for a Root node that has been measured.
*
* @param rootViewTag {@link int} Tag of the root node
*/
public void enableLayoutCalculationForRootNode(int rootViewTag) {
this.mMeasuredRootNodes.add(rootViewTag);
}
}