RenderObject class Null safety

An object in the render tree.

The RenderObject class hierarchy is the core of the rendering library's reason for being.

RenderObjects have a parent, and have a slot called parentData in which the parent RenderObject can store child-specific data, for example, the child position. The RenderObject class also implements the basic layout and paint protocols.

The RenderObject class, however, does not define a child model (e.g. whether a node has zero, one, or more children). It also doesn't define a coordinate system (e.g. whether children are positioned in Cartesian coordinates, in polar coordinates, etc) or a specific layout protocol (e.g. whether the layout is width-in-height-out, or constraint-in-size-out, or whether the parent sets the size and position of the child before or after the child lays out, etc; or indeed whether the children are allowed to read their parent's parentData slot).

The RenderBox subclass introduces the opinion that the layout system uses Cartesian coordinates.

Lifecycle

A RenderObject must dispose when it is no longer needed. The creator of the object is responsible for disposing of it. Typically, the creator is a RenderObjectElement, and that element will dispose the object it creates when it is unmounted.

RenderObjects are responsible for cleaning up any expensive resources they hold when dispose is called, such as Picture or Image objects. This includes any Layers that the render object has directly created. The base implementation of dispose will nullify the layer property. Subclasses must also nullify any other layer(s) it directly creates.

Writing a RenderObject subclass

In most cases, subclassing RenderObject itself is overkill, and RenderBox would be a better starting point. However, if a render object doesn't want to use a Cartesian coordinate system, then it should indeed inherit from RenderObject directly. This allows it to define its own layout protocol by using a new subclass of Constraints rather than using BoxConstraints, and by potentially using an entirely new set of objects and values to represent the result of the output rather than just a Size. This increased flexibility comes at the cost of not being able to rely on the features of RenderBox. For example, RenderBox implements an intrinsic sizing protocol that allows you to measure a child without fully laying it out, in such a way that if that child changes size, the parent will be laid out again (to take into account the new dimensions of the child). This is a subtle and bug-prone feature to get right.

Most aspects of writing a RenderBox apply to writing a RenderObject as well, and therefore the discussion at RenderBox is recommended background reading. The main differences are around layout and hit testing, since those are the aspects that RenderBox primarily specializes.

Layout

A layout protocol begins with a subclass of Constraints. See the discussion at Constraints for more information on how to write a Constraints subclass.

The performLayout method should take the constraints, and apply them. The output of the layout algorithm is fields set on the object that describe the geometry of the object for the purposes of the parent's layout. For example, with RenderBox the output is the RenderBox.size field. This output should only be read by the parent if the parent specified parentUsesSize as true when calling layout on the child.

Anytime anything changes on a render object that would affect the layout of that object, it should call markNeedsLayout.

Hit Testing

Hit testing is even more open-ended than layout. There is no method to override, you are expected to provide one.

The general behavior of your hit-testing method should be similar to the behavior described for RenderBox. The main difference is that the input need not be an Offset. You are also allowed to use a different subclass of HitTestEntry when adding entries to the HitTestResult. When the handleEvent method is called, the same object that was added to the HitTestResult will be passed in, so it can be used to track information like the precise coordinate of the hit, in whatever coordinate system is used by the new layout protocol.

Adapting from one protocol to another

In general, the root of a Flutter render object tree is a RenderView. This object has a single child, which must be a RenderBox. Thus, if you want to have a custom RenderObject subclass in the render tree, you have two choices: you either need to replace the RenderView itself, or you need to have a RenderBox that has your class as its child. (The latter is the much more common case.)

This RenderBox subclass converts from the box protocol to the protocol of your class.

In particular, this means that for hit testing it overrides RenderBox.hitTest, and calls whatever method you have in your class for hit testing.

Similarly, it overrides performLayout to create a Constraints object appropriate for your class and passes that to the child's layout method.

Layout interactions between render objects

In general, the layout of a render object should only depend on the output of its child's layout, and then only if parentUsesSize is set to true in the layout call. Furthermore, if it is set to true, the parent must call the child's layout if the child is to be rendered, because otherwise the parent will not be notified when the child changes its layout outputs.

It is possible to set up render object protocols that transfer additional information. For example, in the RenderBox protocol you can query your children's intrinsic dimensions and baseline geometry. However, if this is done then it is imperative that the child call markNeedsLayout on the parent any time that additional information changes, if the parent used it in the last layout phase. For an example of how to implement this, see the RenderBox.markNeedsLayout method. It overrides RenderObject.markNeedsLayout so that if a parent has queried the intrinsic or baseline information, it gets marked dirty whenever the child's geometry changes.

Inheritance
Implemented types
Mixed in types
Implementers

Constructors

RenderObject()
Initializes internal fields for subclasses.

Properties

alwaysNeedsCompositing bool
Whether this render object always needs compositing.
protected">@protectedread-only
attached bool
Whether this node is in a tree whose root is attached to something.
read-onlyinherited
constraints Constraints
The layout constraints most recently supplied by the parent.
protected">@protectedread-only
debugCanParentUseSize bool
Whether the parent render object is permitted to use this render object's size.
read-only
debugCreator Object?
The object responsible for creating this render object.
read / write
debugDisposed bool?
Whether this has been disposed.
read-only
debugDoingThisLayout bool
Whether performLayout for this render object is currently running.
read-only
debugDoingThisLayoutWithCallback bool
Whether invokeLayoutCallback for this render object is currently running.
read-only
debugDoingThisPaint bool
Whether paint for this render object is currently running.
read-only
debugDoingThisResize bool
Whether performResize for this render object is currently running.
read-only
debugLayer ContainerLayer?
In debug mode, the compositing layer that this render object uses to repaint.
read-only
debugNeedsCompositedLayerUpdate bool
Whether this render object's layer information is dirty.
read-only
debugNeedsLayout bool
Whether this render object's layout information is dirty.
read-only
debugNeedsPaint bool
Whether this render object's paint information is dirty.
read-only
debugSemantics SemanticsNode?
The semantics of this render object.
read-only
depth int
The depth of this node in the tree.
read-onlyinherited
hashCode int
The hash code for this object.
read-onlyinherited
isRepaintBoundary bool
Whether this render object repaints separately from its parent.
read-only
layer ContainerLayer?
The compositing layer that this render object uses to repaint.
protected">@protectedprotected">@protectedread / write
needsCompositing bool
Whether we or one of our descendants has a compositing layer.
read-only
owner PipelineOwner?
The owner for this node (null if unattached).
read-onlyoverride
paintBounds Rect
An estimate of the bounds within which this render object will paint. Useful for debugging flags such as debugPaintLayerBordersEnabled.
read-only
parent AbstractNode?
The parent of this node in the tree.
read-onlyinherited
parentData ParentData?
Data for use by the parent render object.
read / write
runtimeType Type
A representation of the runtime type of the object.
read-onlyinherited
semanticBounds Rect
The bounding box, in the local coordinate system, of this object, for accessibility purposes.
read-only
sizedByParent bool
Whether the constraints are the only input to the sizing algorithm (in particular, child nodes have no impact).
protected">@protectedread-only

Methods

adoptChild(covariant RenderObject child) → void
Called by subclasses when they decide a render object is a child.
override
applyPaintTransform(covariant RenderObject child, Matrix4 transform) → void
Applies the transform that would be applied when painting the given child to the given matrix.
assembleSemanticsNode(SemanticsNode node, SemanticsConfiguration config, Iterable<SemanticsNode> children) → void
Assemble the SemanticsNode for this RenderObject.
attach(covariant PipelineOwner owner) → void
Mark this node as attached to the given owner.
override
clearSemantics() → void
Removes all semantics from this render object and its descendants.
mustCallSuper">@mustCallSuper
debugAssertDoesMeetConstraints() → void
Verify that the object's constraints are being met. Override this function in a subclass to verify that your state matches the constraints object. This function is only called in checked mode and only when needsLayout is false. If the constraints are not met, it should assert or throw an exception.
protected">@protected
debugDescribeChildren() List<DiagnosticsNode>
Returns a list of DiagnosticsNode objects describing this node's children.
override
debugFillProperties(DiagnosticPropertiesBuilder properties) → void
Add additional properties associated with the node.
protected">@protectedoverride
debugPaint(PaintingContext context, Offset offset) → void
Override this method to paint debugging information.
debugRegisterRepaintBoundaryPaint({bool includedParent = true, bool includedChild = false}) → void
Called, in debug mode, if isRepaintBoundary is true, when either the this render object or its parent attempt to paint.
debugResetSize() → void
If a subclass has a "size" (the state controlled by parentUsesSize, whatever it is in the subclass, e.g. the actual size property of RenderBox), and the subclass verifies that in debug mode this "size" property isn't used when debugCanParentUseSize isn't set, then that subclass should override debugResetSize to reapply the current values of debugCanParentUseSize to that state.
protected">@protected
describeApproximatePaintClip(covariant RenderObject child) Rect?
Returns a rect in this object's coordinate system that describes the approximate bounding box of the clip rect that would be applied to the given child during the paint phase, if any.
describeForError(String name, {DiagnosticsTreeStyle style = DiagnosticsTreeStyle.shallow}) DiagnosticsNode
Adds a debug representation of a RenderObject optimized for including in error messages.
describeSemanticsClip(covariant RenderObject? child) Rect?
Returns a rect in this object's coordinate system that describes which SemanticsNodes produced by the child should be included in the semantics tree. SemanticsNodes from the child that are positioned outside of this rect will be dropped. Child SemanticsNodes that are positioned inside this rect, but outside of describeApproximatePaintClip will be included in the tree marked as hidden. Child SemanticsNodes that are inside of both rect will be included in the tree as regular nodes.
describeSemanticsConfiguration(SemanticsConfiguration config) → void
Report the semantics of this node, for example for accessibility purposes.
protected">@protected
detach() → void
Mark this node as detached.
mustCallSuper">@mustCallSuperinherited
dispose() → void
Release any resources held by this render object.
mustCallSuper">@mustCallSuper
dropChild(covariant RenderObject child) → void
Called by subclasses when they decide a render object is no longer a child.
override
getTransformTo(RenderObject? ancestor) Matrix4
Applies the paint transform up the tree to ancestor.
handleEvent(PointerEvent event, covariant HitTestEntry<HitTestTarget> entry) → void
Override this method to handle pointer events that hit this render object.
override
invokeLayoutCallback<T extends Constraints>(LayoutCallback<T> callback) → void
Allows mutations to be made to this object's child list (and any descendants) as well as to any other dirty nodes in the render tree owned by the same PipelineOwner as this object. The callback argument is invoked synchronously, and the mutations are allowed only during that callback's execution.
protected">@protected
layout(Constraints constraints, {bool parentUsesSize = false}) → void
Compute the layout for this render object.
markNeedsCompositedLayerUpdate() → void
Mark this render object as having changed a property on its composited layer.
markNeedsCompositingBitsUpdate() → void
Mark the compositing state for this render object as dirty.
markNeedsLayout() → void
Mark this render object's layout information as dirty, and either register this object with its PipelineOwner, or defer to the parent, depending on whether this object is a relayout boundary or not respectively.
markNeedsLayoutForSizedByParentChange() → void
Mark this render object's layout information as dirty (like markNeedsLayout), and additionally also handle any necessary work to handle the case where sizedByParent has changed value.
markNeedsPaint() → void
Mark this render object as having changed its visual appearance.
markNeedsSemanticsUpdate() → void
Mark this node as needing an update to its semantics description.
markParentNeedsLayout() → void
Mark this render object's layout information as dirty, and then defer to the parent.
protected">@protected
noSuchMethod(Invocation invocation) → dynamic
Invoked when a non-existent method or property is accessed.
inherited
paint(PaintingContext context, Offset offset) → void
Paint this render object into the given context at the given offset.
paintsChild(covariant RenderObject child) bool
Whether the given child would be painted if paint were called.
performLayout() → void
Do the work of computing the layout for this render object.
protected">@protected
performResize() → void
Updates the render objects size using only the constraints.
protected">@protected
reassemble() → void
Cause the entire subtree rooted at the given RenderObject to be marked dirty for layout, paint, etc, so that the effects of a hot reload can be seen, or so that the effect of changing a global debug flag (such as debugPaintSizeEnabled) can be applied.
redepthChild(AbstractNode child) → void
Adjust the depth of the given child to be greater than this node's own depth.
protected">@protectedinherited
redepthChildren() → void
Adjust the depth of this node's children, if any.
inherited
replaceRootLayer(OffsetLayer rootLayer) → void
Replace the layer. This is only valid for the root of a render object subtree (whatever object scheduleInitialPaint was called on).
scheduleInitialLayout() → void
Bootstrap the rendering pipeline by scheduling the very first layout.
scheduleInitialPaint(ContainerLayer rootLayer) → void
Bootstrap the rendering pipeline by scheduling the very first paint.
scheduleInitialSemantics() → void
Bootstrap the semantics reporting mechanism by marking this node as needing a semantics update.
sendSemanticsEvent(SemanticsEvent semanticsEvent) → void
Sends a SemanticsEvent associated with this render object's SemanticsNode.
setupParentData(covariant RenderObject child) → void
Override to setup parent data correctly for your children.
showOnScreen({RenderObject? descendant, Rect? rect, Duration duration = Duration.zero, Curve curve = Curves.ease}) → void
Attempt to make (a portion of) this or a descendant RenderObject visible on screen.
toDiagnosticsNode({String? name, DiagnosticsTreeStyle? style}) DiagnosticsNode
Returns a debug representation of the object that is used by debugging tools and by DiagnosticsNode.toStringDeep.
inherited
toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) String
A string representation of this object.
override
toStringDeep({String prefixLineOne = '', String? prefixOtherLines = '', DiagnosticLevel minLevel = DiagnosticLevel.debug}) String
Returns a description of the tree rooted at this node. If the prefix argument is provided, then every line in the output will be prefixed by that string.
override
toStringShallow({String joiner = ', ', DiagnosticLevel minLevel = DiagnosticLevel.debug}) String
Returns a one-line detailed description of the render object. This description is often somewhat long.
override
toStringShort() String
Returns a human understandable name.
override
updateCompositedLayer({required covariant OffsetLayer? oldLayer}) OffsetLayer
Update the composited layer owned by this render object.
visitChildren(RenderObjectVisitor visitor) → void
Calls visitor for each immediate child of this render object.
visitChildrenForSemantics(RenderObjectVisitor visitor) → void
Called when collecting the semantics of this node.

Operators

operator ==(Object other) bool
The equality operator.
inherited

Static Properties

debugActiveLayout RenderObject?
The render object that is actively computing layout.
read-only
debugActivePaint RenderObject?
The render object that is actively painting.
read-only
debugCheckingIntrinsics bool
When true, debugAssertDoesMeetConstraints() is currently executing asserts for verifying the consistent behavior of intrinsic dimensions methods.
read / write