Box Model
What are the render box building blocks?
RenderBox
models a box in 2D cartesian coordinates with a width, height, and offset. The origin of the box is the top-left corner (0,0), with the bottom-right corner corresponding to (width, height).BoxParentData
stores a child’s position in the parent’s coordinate space. It is opaque to the child by convention.BoxConstraints
provide cartesian constraints in the form of a maximum and minimum width and height between 0 and infinity, inclusive. Constraints are satisfied for all dimensions simultaneously within the given inclusive range.Constraints are normalized when min is less or equal to max.
Constraints are tight when max and min are equal.
Constraints are loose when min is 0, even if max is also 0 (loose and tight).
Constraints are bounded when max is not infinite.
Constraints are unbounded when max is infinite.
Constraints are expanding when tightly infinite.
Constraints are infinite when min is infinite (max must also be infinite; thus, this is also expanding).
BoxHitTestResult
is an aggregator that collects the entries associated with a single hit test query.BoxHitTestResult
includes several box-specific helpers, i.e.,BoxHitTestResult.addWithPaintOffset
,BoxHitTestResult.addWithPaintTransform
, etc.BoxHitTestEntry
represents a box that was hit during hit testing. It captures the position of the collision in local coordinates (BoxHitTestEntry.localPosition
).
What are the render box tree building blocks?
RenderProxyBox
supports a singleRenderBox
child, delegating all methods to said child.RenderShiftedBox
is identical, but offsets the child usingBoxParentData.offset
and requires a layout implementation. Both are built withRenderObjectWithChildMixin
.RenderObjectWithChildMixin
andContainerRenderObjectMixin
can both be used with a type argument ofRenderBox
. TheContainerRenderObjectMixin
accepts a parent data type argument, as well;ContainerBoxParentData
satisfies the type constraints and supports box parent data.RenderBoxContainerDefaultsMixin
adds useful defaults toContainerRenderObjectMixin
for render boxes. This includes support for hit testing and painting children, as well as computing baselines.
How do render boxes handle layout?
RenderBox
layout is the same asRenderObject
layout, with the input beingBoxConstraints
and the output beingRenderBox.size
(Size). Layout typically also sets the position (BoxParentData.offset
) of any children, though the child may not read this data.The
RenderBox
protocol includes support for intrinsic dimensions (a size that is computed outside of the layout protocol) as well as baselines (the bottom of the box for vertical alignment).RenderBox
instances track changes to these values and whether the parent has queried them; if so, when that box is marked as needing layout, the parent is marked as well.Marking a render box as needing layout implies that the box needs paint. Building a render box implies both.
Render boxes can have non-box children. In this case, the constraints passed from the parent to the child will need to be adapted from
BoxConstraints
to the new protocol.
How do render boxes handle paint?
Painting is the same as
RenderObject
painting. The offset provided corresponds to the origin of the render object in the canvas’s coordinate space (which may not be the same).If the render box applies a transform when painting, including painting at a different offset than the one provided,
RenderBox.applyPaintTransform
must apply the same transformation.RenderBox.globalToLocal
andRenderBox.localToGlobal
rely on this transform to map cartesian coordinates.By default,
RenderBox.applyPaintTransform
will apply the child’s offset to the matrix as a translation.
How do render boxes handle hit testing?
All
RenderBoxes
must implementRenderBox.hitTest
, which by default delegates toRenderBox.hitTestChildren
andRenderBox.hitTestSelf
, in that order. Note that items added to theBoxHitTestResult
first are treated as being on top of those added later. All entries in theBoxHitTestResult
are fed events from the corresponding event stream viaRenderBox.handleEvent
.
What are intrinsic dimensions?
Conceptually, the intrinsic dimensions of a box are its natural dimensions -- the size it “wants” to be. Given that this definition is subjective, it is left as an implementation detail what exactly this means for a given render object. Note that intrinsic dimensions are often defined in terms of child intrinsic dimensions and are therefore expensive to calculate (typically traversing an entire subtree).
Intrinsic dimensions often do not match the dimensions resulting from layout (except when using the
IntrinsicHeight
andIntrinsicWidth
widgets, which attempt to layout their child using its intrinsic dimensions).Intrinsic dimensions are generally ignored unless one of these widgets are used (or another widget that explicitly incorporates intrinsic dimensions into its own layout).
The render box model describes intrinsic dimensions in terms of minimum and maximum values for width and height.
Minimum intrinsic width is the smallest width before the box cannot paint correctly without clipping.
Intuition: making the box thinner would clip its contents.
If width is determined by height (ignoring constraints), the incoming height (which may be infinite, i.e., unconstrained) should be used. Otherwise, ignore the height.
Minimum intrinsic height is the same concept for height.
Maximum intrinsic width is the smallest width such that further expansion would not reduce minimum intrinsic height (for that width).
Intuition: making the box wider won’t help fit more content.
If width is determined by height (ignoring constraints), the incoming height (which may be infinite, i.e., unconstrained) should be used. Otherwise, ignore the height.
Maximum intrinsic height is the same concept for height.
The specific meaning of intrinsic dimensions depends on the implementation.
Text is width-in-height-out.
Max intrinsic width: the width of the string without line breaks (increasing the width would not shrink the preferred height).
Min intrinsic width: the width of the widest word (decreasing the width would clip the word or cause an invalid break).
Height intrinsics derived from width intrinsics for the given width.
Viewports ignore incoming constraints and aggregate child dimensions without clipping.
Aspect ratio boxes are entirely determined when one dimension is provided.
Use the incoming dimension to compute the other. If unconstrained, recurse.
When intrinsic dimensions cannot be computed or are too expensive, return zero.
What are baselines?
Baselines are used to vertically align children independent of font size, padding, etc. When a real baseline isn’t available, the bottom of the render box is used. Baselines are expressed as an offset from the box’s y-coordinate; if there are multiple children, the first sets the baseline.
Only a render box’s parent can invoke
RenderBox.getDistanceToBaseline
, and only after that render box has been laid out in the parent’sRenderBox.performLayout
method.
Last updated