layoutPositionedChild static method

void layoutPositionedChild(
  1. RenderBoxModel parent,
  2. RenderBoxModel child, {
  3. bool needsRelayout = false,
})

Implementation

static void layoutPositionedChild(RenderBoxModel parent, RenderBoxModel child, {bool needsRelayout = false}) {
  BoxConstraints childConstraints = child.getConstraints();

  // For absolutely/fixed positioned non-replaced elements with both top and bottom specified
  // and height:auto, compute the used border-box height from the containing block when the
  // containing block's padding-box height is known. This mirrors the horizontal auto-width
  // solver in RenderBoxModel.getConstraints and allows patterns like `top:0; bottom:0`
  // overlays to stretch with the container height. Do this only when there are no explicit
  // min/max height constraints so we don't override author-specified clamping (e.g., max-height).
  final CSSRenderStyle rs = child.renderStyle;
  final bool isAbsOrFixed = rs.position == CSSPositionType.absolute || rs.position == CSSPositionType.fixed;
  final bool hasExplicitMaxHeight = !rs.maxHeight.isNone;
  final bool hasExplicitMinHeight = !rs.minHeight.isAuto;
  if (isAbsOrFixed &&
      !rs.isSelfRenderReplaced() &&
      rs.height.isAuto &&
      rs.top.isNotAuto &&
      rs.bottom.isNotAuto &&
      !hasExplicitMaxHeight &&
      !hasExplicitMinHeight &&
      parent.hasSize &&
      parent.boxSize != null) {
    final CSSRenderStyle prs = parent.renderStyle;
    final Size parentSize = parent.boxSize!;
    final double cbHeight = math.max(
      0.0,
      parentSize.height -
          prs.effectiveBorderTopWidth.computedValue -
          prs.effectiveBorderBottomWidth.computedValue,
    );
    double solvedBorderBoxHeight = cbHeight -
        rs.top.computedValue -
        rs.bottom.computedValue -
        rs.marginTop.computedValue -
        rs.marginBottom.computedValue;
    solvedBorderBoxHeight = math.max(0.0, solvedBorderBoxHeight);
    if (solvedBorderBoxHeight.isFinite) {
      childConstraints = BoxConstraints(
        minWidth: childConstraints.minWidth,
        maxWidth: childConstraints.maxWidth,
        minHeight: solvedBorderBoxHeight,
        maxHeight: solvedBorderBoxHeight,
      );
    }
  }

  // Whether child need to layout
  bool isChildNeedsLayout = true;
  if (child.hasSize && !needsRelayout && (childConstraints == child.constraints) && (!child.needsLayout)) {
    isChildNeedsLayout = false;
  }

  if (isChildNeedsLayout) {
    try {
      PositionedLayoutLog.log(
        impl: PositionedImpl.layout,
        feature: PositionedFeature.layout,
        message: () => '<${child.renderStyle.target.tagName.toLowerCase()}> layout start '
            'constraints=(${childConstraints.minWidth.toStringAsFixed(1)}..${childConstraints.maxWidth.isFinite ? childConstraints.maxWidth.toStringAsFixed(1) : '∞'}, '
            '${childConstraints.minHeight.toStringAsFixed(1)}..${childConstraints.maxHeight.isFinite ? childConstraints.maxHeight.toStringAsFixed(1) : '∞'})',
      );
    } catch (_) {}
    // Should create relayoutBoundary for positioned child.
    child.layout(childConstraints, parentUsesSize: false);
    try {
      final Size s = child.size;
      PositionedLayoutLog.log(
        impl: PositionedImpl.layout,
        feature: PositionedFeature.layout,
        message: () => '<${child.renderStyle.target.tagName.toLowerCase()}> layout done size=${s.width.toStringAsFixed(2)}×${s.height.toStringAsFixed(2)}',
      );
    } catch (_) {}
  }
}