diff --git a/ReactCommon/fabric/core/layout/LayoutableShadowNode.cpp b/ReactCommon/fabric/core/layout/LayoutableShadowNode.cpp index aa296769a69..786cd410816 100644 --- a/ReactCommon/fabric/core/layout/LayoutableShadowNode.cpp +++ b/ReactCommon/fabric/core/layout/LayoutableShadowNode.cpp @@ -31,6 +31,10 @@ bool LayoutableShadowNode::setLayoutMetrics(LayoutMetrics layoutMetrics) { return true; } +bool LayoutableShadowNode::LayoutableShadowNode::isLayoutOnly() const { + return false; +} + void LayoutableShadowNode::cleanLayout() { isLayoutClean_ = true; } diff --git a/ReactCommon/fabric/core/layout/LayoutableShadowNode.h b/ReactCommon/fabric/core/layout/LayoutableShadowNode.h index febc222cfea..5cf49ebaef0 100644 --- a/ReactCommon/fabric/core/layout/LayoutableShadowNode.h +++ b/ReactCommon/fabric/core/layout/LayoutableShadowNode.h @@ -52,6 +52,13 @@ public: */ virtual LayoutMetrics getLayoutMetrics() const; + /* + * Returns `true` if the node represents only information necessary for + * layout computation and can be safely removed from view hierarchy. + * Default implementation returns `false`. + */ + virtual bool isLayoutOnly() const; + protected: /* diff --git a/ReactCommon/fabric/uimanager/Differentiator.cpp b/ReactCommon/fabric/uimanager/Differentiator.cpp index 43b83785085..3e69be60bf3 100644 --- a/ReactCommon/fabric/uimanager/Differentiator.cpp +++ b/ReactCommon/fabric/uimanager/Differentiator.cpp @@ -11,13 +11,27 @@ namespace facebook { namespace react { +static void sliceChildShadowNodeViewPairsRecursively(ShadowViewNodePairList &pairList, Point layoutOffset, const ShadowNode &shadowNode) { + for (const auto &childShadowNode : shadowNode.getChildren()) { + auto shadowView = ShadowView(*childShadowNode); + + const auto layoutableShadowNode = dynamic_cast(childShadowNode.get()); + if (layoutableShadowNode && layoutableShadowNode->isLayoutOnly()) { + sliceChildShadowNodeViewPairsRecursively( + pairList, + layoutOffset + shadowView.layoutMetrics.frame.origin, + *childShadowNode + ); + } else { + shadowView.layoutMetrics.frame.origin += layoutOffset; + pairList.push_back({shadowView, *childShadowNode}); + } + } +} + static ShadowViewNodePairList sliceChildShadowNodeViewPairs(const ShadowNode &shadowNode) { ShadowViewNodePairList pairList; - - for (const auto &childShadowNode : shadowNode.getChildren()) { - pairList.push_back({ShadowView(*childShadowNode), *childShadowNode}); - } - + sliceChildShadowNodeViewPairsRecursively(pairList, {0, 0}, shadowNode); return pairList; }