RenderObject._relayoutBoundary) that meets a set of criteria allowing it to layout independently of its parent. That is, the subtree rooted at a relayout boundary node can never invalidate nodes outside of that subtree.
!parentUsesSize), fully determines its size (
sizedByParent), provides tight constraints, or isn't a render object (e.g.,
parentUsesSizeparameter prevents a render object from becoming a relayout boundary. As a consequence, when the render object is marked dirty, all ancestors up to the nearest relayout boundary will be marked dirty, including the parent.
RenderObject.layoutis responsible for applying this logic.
RenderObject._layoutWithoutResizeperforms layout unconditionally since
PipelineOwner.flushLayoutalready skips clean nodes.
PipelineOwnermaintains a list of dirty nodes (
PipelineOwner._nodeNeedingLayout) that are cleaned once per frame (via
RenderObject.markNeedsLayout, which sets
RenderObject._needsLayout) , all ancestors up to and including the nearest relayout boundary are marked dirty (via
PipelineOwner._nodeNeedingLayout. Performing layout on this node will recursively layout all descendants. This also schedules the next frame (via
PipelineOwner.requestVisualUpdate) so that layout changes will be applied (via
PipelineOwner.flushLayoutignores any clean nodes.
sizedByParentbit changes (via
RenderObject.markNeedsLayoutForSizedByParentChange). Updating this bit can add or remove a relayout boundary from the render tree (the change is committed subsequently by
RenderObject.layout). Most render objects do not update this bit dynamically.
RenderObject._layoutWithoutResize, which doesn't update relayout boundaries. Thus, since the child may change status, its parent must be laid out, too.
RenderViewprovides the topmost constraints (via
RenderView.performLayout) as read from the view configuration (
ViewConfiguration.size). This represents the overall dimensions of the viewing surface in logical units.
RenderObject.constraints). These constraints cannot be invalid; otherwise, a node further up the tree would have been marked dirty.
RenderObject.performLayout) may affect the constraints provided to children; constraints may also be entirely arbitrary (e.g.,
OverflowBox). These constraints are forwarded to any children, which repeat the process recursively.
PipelineOwner.flushLayouttriggers layout for all nodes in the dirty list (
PipelineOwner._nodesNeedingLayout) in order of increasing depth. The nodes in this list correspond to relayout boundaries and are laid out using
RenderObject.performResizeis never necessary for a node in the dirty list. Consider a node that is sized by its parent:
RenderObject._layoutWithoutResizenever updates cached constraints (
RenderObject.constraints) or the relayout boundary (
RenderObject.layout) if it's been marked dirty or has received new constraints, or has just become a relayout boundary. Otherwise, it will mark itself clean and cut off the walk.
RenderObject.layoutcaches new constraints (
RenderObject.constraints) and propagates any changes to the relayout boundary field (
RenderObject._relayoutBoundary) to affected descendants (via
RenderObject.sizedByParent) adopt a new size using the incoming constraints alone (via
RenderObject.performResize). All render objects — including those that were resized — proceed with layout (via
RenderObject.layout) and updating each child's parent data.
RenderObject.layoutmarks the object as needing semantics and painting, but no longer needing layout.
sizedByParent” (the provided constraints solely determine the size), and the same constraints are passed again, the parent needn’t be laid out with the child; the child cannot change size.
RenderObject._relayoutBoundary) is maintained as layout progresses down the tree. When layout is performed (via
RenderObject.performLayout), the render object determines whether it meets any of the optimization criteria described above. If so, it sets itself as the nearest relayout boundary. Otherwise, it adopts its parent's relayout boundary.
RenderObject._cleanRelayoutBoundary). The walk stops at descendants that themselves demarcate a relayout boundary (i.e.,
RenderObject._relayoutBoundary == this).
RenderObject.invokeLayoutCallbackallows a builder callback to be invoked during the layout process. Only subtrees that are still dirty may be manipulated which ensures that nodes are laid out exactly once. This allows children to be built on-demand during layout (needed for viewports) and nodes to be moved (needed for global key reparenting).
Containerprovides a consistent interface to a number of more fundamental layout building blocks. Unless otherwise specified, each box is sized to match its child.
ConstrainedBoxapplies an extra set of constraints in addition to the incoming constraints. The extra constraints are clamped to the incoming constraints (via
BoxConstraints.enforce) and thus may not violate them. The box becomes as small as possible without a child.
ConstrainedBox, providing tight constraints for the specified dimensions. The result is that the child will be sized to these dimensions subject to the incoming constraints. The box is still sized even without a child.
UnconstrainedBoxlays out its child with unbounded constraints (in one or more dimensions). It then sizes itself to match the child subject to incoming constraints (i.e., to prevent any actual overflow). An alignment is applied if the child is a different size than its parent. If there would have been overflow, the child’s painting is clipped accordingly. The box becomes as small as possible without a child.
OverflowBoxallows one or more components of the incoming constraints to be completely overwritten. The child is laid out using the altered constraints and therefore may overflow. An alignment is applied if the child is a different size than its parent. In all other ways, this box delegates to the child.
SizedOverflowBoxassumes a specific size, subject to the incoming constraints. Its child is laid out using the original constraints, however, and therefore may overflow the parent (e.g., if the incoming constraints permit a size of up to 100x100, and the parent specifies a size of 50x50, the child can select a larger size, overflowing its parent). Since this box has an explicit size, its given intrinsic dimensions matching this size.
FractionallySizedBoxsizes its child in proportion to the incoming constraints; it sizes itself to the child, but without violating the original constraints. In particular, the maximum constraints are multiplied by a corresponding factor to obtain a tight bound (if a factor isn’t specified, that dimension’s constraints are left unchanged). The child is laid out using the new constraints and may therefore overflow the parent. The parent is sized to the child subject to the incoming constraints, and therefore cannot overflow; note that painting and hit testing will not be automatically clipped. Intrinsic dimensions are defined as the child’s intrinsic dimension scaled by the corresponding factor.
LimitedBoxapplies a maximum width or height only when the corresponding constraint is unbounded. That is, when the incoming constraints are forwarded to the child, the maximum constraint in each dimension is set to a specific value if it is otherwise unbounded. This is typically used to place expanding children into containers with infinite dimensions (e.g., viewports).
Paddingapplies spacing around its child (via
EdgeInsetsGeometry). This is achieved by providing the child with constraints deflated by the padding. The parent assumes the size of the child (which is zero if there is no child) inflated by the padding.
EdgeInsetsGeometrydescribes offsets in the four cardinal directions.
EdgeInsetsspecifies the offsets with absolute positioning (e.g., left, top, right, bottom) whereas
EdgeInsetsDirectionalis text-orientation sensitive (e.g., start, top, end, bottom). Both allow offsets to be combined, subtracted, inflated, and deflated, as well as queried along an axis.
Transformapplies a transformation matrix during painting. It does not alter layout, delegating entirely to
RenderProxyBoxfor these purposes. If the transform can solely be described as a translation, it delegates to its parent for painting, as well. Otherwise, it composites the corresponding transformation before painting its child. Optionally, this transform may be applied before hit testing (via
BoxFitto its child.
BoxFitspecifies how a child box is to be inscribed within a parent box (e.g.,
BoxFit.fitWidthscales the width to fit the parent and the height to maintain the aspect ratio, possibly overflowing the parent;
BoxFit.scaleDownaligns the child within the parent then scales to ensure that the child does not overflow). The child is laid out without constraint, then scaled to be as large as possible while maintaining the original aspect ratio and respecting the incoming constraints. The box fit determines a transformation matrix that is applied during painting.
applyBoxFit, which considers each box’s size without respect to positioning. The result is a
FittedSizesinstance, which describes a region within the child (the source) and a region within the parent (the destination). In particular, the source measures the portion of the child visible within the parent (e.g., if this is smaller than the child, the child will be clipped). The destination measures the portion of the parent occupied by the child (e.g., if this is smaller than the parent, a portion of the parent will remain visible).
Alignment.inscribe). Finally, a transformation is composed to translate and scale the child relative to the parent as per the calculated rectangles.
Baselinealigns a child such that its baseline is coincident with its own (as specified). The child’s baseline is obtained via
RenderBox.getDistanceToBaselineand an offset calculated to ensure the child’s baseline is coincident with the target line (itself expressed as an offset from the box’s top). As a result, though the parent is sized to contain the child, the offset may cause the parent to be larger (e.g., if the child is shifted below the parent’s top).
Alignallows a child to be aligned within a parent according to a relative position specified via
AlignmentGeometry. During layout, the child is positioned according to the alignment (via
RenderAligningShiftedBox.alignChild, which invokes
AlignmentGeometry.alongOffset; this maps the alignment to logical coordinates using simple geometry). Note that the child must undergo layout beforehand since its size is needed to compute its center; the incoming constraints are loosened before being forwarded to the child. Next, the parent is sized according to whether a width or height factor was specified; if so, the corresponding dimension will be set to a multiple of that of the child (subject to the incoming constraints). Otherwise, it will expand to fill the constraints. If the incoming constraints are unbounded, the parent will instead shrinkwrap the child.
Alignmentis a subclass of
AlignmentGeometrythat describes a point within a container using units relative to the container’s size and center. The child’s center is positioned such that it is coincident with this point. Each unit is measured as half the container’s corresponding dimension (e.g., the container is effectively 2 units wide and 2 units tall). The center of the container corresponds to (0, 0), the top left to (-1, -1), and the bottom right to (1, 1). Units may overflow this range to specify different multiple of the parent’s size.
AlignmentDirectionalis identical but flips the x-axis for right-to-left languages.
FractionalOffsetrepresents a relative position as a fraction of the container’s size, measured from its top left corner. The child’s top-left corner is positioned such that it is coincident with this point. The center of the container corresponds to (
0.5), the top left to (0, 0), and the bottom right to (1, 1).
IntrinsicWidthintegrate the intrinsic dimension and layout protocols. Intrinsic dimensions reflect the natural size of an object; this definition varies based on what the object actually represents. Prior to laying out, the child’s intrinsic dimension is queried (e.g., via
RenderBox.getMaxIntrinsicWidth). Next, the incoming constraints are tightened to reflect the resulting value. Finally, the child is laid out using the tight constraints. In this way, the child’s intrinsic size is used in determining its actual size (the two will only match if permitted by the incoming constraints).
LayoutBuildermakes it easy to take advantage of interleaving the build / layout phase via callbacks. The callback has access to the incoming constraints (i.e., because the framework has completed building and is currently performing layout) but may still build additional UI (via
RenderObject.invokeLayoutCallback). Once building is complete, layout continues through the subtree and beyond.
CustomSingleChildLayoutallows its layout and its child’s layout to be customized without implementing a new render box. Deferring to a delegate, the associated
SingleChildLayoutDelegate.getSizeto size the parent, then
SingleChildLayoutDelegate.getConstraintsForChildto constrain the child, and finally
SingleChildLayoutDelegate.getPositionForChildto position the child.
CustomMultiChildLayoutis similar, but supports multiple children. To identify children, each must be tagged with a
ParentDataWidgetthat stores an identifier in each child’s
MultiChildLayoutParentData(recall that render objects establish their children’s parent data type).
MultiChildLayoutDelegatebehaves similarly to its single-child variant; override
MultiChildLayoutDelegate.performLayoutto size and position each child via
MultiChildLayoutDelegate.positionChild, respectively (the latter must be called once per child in any order).