Let containing blocks layout their absolute descendants, not parents (#1470)
Summary: X-link: https://github.com/facebook/react-native/pull/41488 Pull Request resolved: https://github.com/facebook/yoga/pull/1470 The way we plan on implementing `position: static` is by changing how we lay out absolutely positioned nodes. Instead of letting their direct parent lay them out we are going to let their containing block handle it. This is useful because by the time the containing block gets to this step it will already know its size, which is needed to ensure that absolute nodes can get the right value with percentage units. Additionally, it means that we can "translate" the position of the absolute nodes to be relative to their parent fairly easily, instead of some second pass that would not be possible with a different design. This change just gets the core pieces of this process going. It makes it so that containing blocks will layout out absolute descendants that they contain. We also pass in the containing block size to the owner size args for `layoutAbsoluteChild`. This new path will only happen if we have the errata turned off. If there is no positioned ancestor for a given node we just assume the root is. This is not exactly how it works on the web - there is a notion of an initial containing block - but we are not implementing that as of right now. Reviewed By: NickGerleman Differential Revision: D51182593 fbshipit-source-id: 88b5730f7f4fec4f33ec64288618e23363091857
This commit is contained in:
committed by
Facebook GitHub Bot
parent
59bf902a17
commit
5a24c81672
@@ -531,6 +531,45 @@ static void layoutAbsoluteChild(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void layoutAbsoluteDescendants(
|
||||||
|
yoga::Node* currentNode,
|
||||||
|
SizingMode widthSizingMode,
|
||||||
|
Direction currentNodeDirection,
|
||||||
|
LayoutData& layoutMarkerData,
|
||||||
|
uint32_t currentDepth,
|
||||||
|
uint32_t generationCount,
|
||||||
|
float containingBlockWidth,
|
||||||
|
float containingBlockHeight) {
|
||||||
|
for (auto child : currentNode->getChildren()) {
|
||||||
|
if (child->getStyle().display() == Display::None) {
|
||||||
|
continue;
|
||||||
|
} else if (child->getStyle().positionType() == PositionType::Absolute) {
|
||||||
|
layoutAbsoluteChild(
|
||||||
|
currentNode,
|
||||||
|
child,
|
||||||
|
containingBlockWidth,
|
||||||
|
widthSizingMode,
|
||||||
|
containingBlockHeight,
|
||||||
|
currentNodeDirection,
|
||||||
|
layoutMarkerData,
|
||||||
|
currentDepth,
|
||||||
|
generationCount);
|
||||||
|
} else if (child->getStyle().positionType() == PositionType::Static) {
|
||||||
|
const Direction childDirection =
|
||||||
|
child->resolveDirection(currentNodeDirection);
|
||||||
|
layoutAbsoluteDescendants(
|
||||||
|
child,
|
||||||
|
widthSizingMode,
|
||||||
|
childDirection,
|
||||||
|
layoutMarkerData,
|
||||||
|
currentDepth + 1,
|
||||||
|
generationCount,
|
||||||
|
containingBlockWidth,
|
||||||
|
containingBlockHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void measureNodeWithMeasureFunc(
|
static void measureNodeWithMeasureFunc(
|
||||||
yoga::Node* const node,
|
yoga::Node* const node,
|
||||||
float availableWidth,
|
float availableWidth,
|
||||||
@@ -2304,6 +2343,22 @@ static void calculateLayoutImpl(
|
|||||||
|
|
||||||
if (performLayout) {
|
if (performLayout) {
|
||||||
// STEP 10: SIZING AND POSITIONING ABSOLUTE CHILDREN
|
// STEP 10: SIZING AND POSITIONING ABSOLUTE CHILDREN
|
||||||
|
if (!node->hasErrata(Errata::PositionStaticBehavesLikeRelative)) {
|
||||||
|
// Let the containing block layout its absolute descendants. By definition
|
||||||
|
// the containing block will not be static unless we are at the root.
|
||||||
|
if (node->getStyle().positionType() != PositionType::Static ||
|
||||||
|
depth == 1) {
|
||||||
|
layoutAbsoluteDescendants(
|
||||||
|
node,
|
||||||
|
isMainAxisRow ? sizingModeMainDim : sizingModeCrossDim,
|
||||||
|
direction,
|
||||||
|
layoutMarkerData,
|
||||||
|
depth,
|
||||||
|
generationCount,
|
||||||
|
node->getLayout().measuredDimension(Dimension::Width),
|
||||||
|
node->getLayout().measuredDimension(Dimension::Height));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
for (auto child : node->getChildren()) {
|
for (auto child : node->getChildren()) {
|
||||||
if (child->getStyle().display() == Display::None ||
|
if (child->getStyle().display() == Display::None ||
|
||||||
child->getStyle().positionType() != PositionType::Absolute) {
|
child->getStyle().positionType() != PositionType::Absolute) {
|
||||||
@@ -2328,6 +2383,7 @@ static void calculateLayoutImpl(
|
|||||||
depth,
|
depth,
|
||||||
generationCount);
|
generationCount);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// STEP 11: SETTING TRAILING POSITIONS FOR CHILDREN
|
// STEP 11: SETTING TRAILING POSITIONS FOR CHILDREN
|
||||||
const bool needsMainTrailingPos = mainAxis == FlexDirection::RowReverse ||
|
const bool needsMainTrailingPos = mainAxis == FlexDirection::RowReverse ||
|
||||||
|
Reference in New Issue
Block a user