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
).
RenderProxyBox
supports a single RenderBox
child, delegating all methods to said child. RenderShiftedBox
is identical, but offsets the child using BoxParentData.offset
and requires a layout implementation. Both are built with RenderObjectWithChildMixin
.
RenderObjectWithChildMixin
and ContainerRenderObjectMixin
can both be used with a type argument of RenderBox
. The ContainerRenderObjectMixin
accepts a parent data type argument, as well; ContainerBoxParentData
satisfies the type constraints and supports box parent data.
RenderBoxContainerDefaultsMixin
adds useful defaults to ContainerRenderObjectMixin
for render boxes. This includes support for hit testing and painting children, as well as computing baselines.
RenderBox
layout is the same as RenderObject
layout, with the input being BoxConstraints
and the output being RenderBox.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.
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
and RenderBox.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.
All RenderBoxes
must implement RenderBox.hitTest
, which by default delegates to RenderBox.hitTestChildren
and RenderBox.hitTestSelf
, in that order. Note that items added to the BoxHitTestResult
first are treated as being on top of those added later. All entries in the BoxHitTestResult
are fed events from the corresponding event stream via RenderBox.handleEvent
.
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
and IntrinsicWidth
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.
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’s RenderBox.performLayout
method.