CustomPainter class abstract
The interface used by CustomPaint (in the widgets library) and RenderCustomPaint (in the rendering library).
To implement a custom painter, either subclass or implement this interface to define your custom paint delegate. CustomPainter subclasses must implement the paint and shouldRepaint methods, and may optionally also implement the hitTest and shouldRebuildSemantics methods, and the semanticsBuilder getter.
The paint method is called whenever the custom object needs to be repainted.
The shouldRepaint method is called when a new instance of the class is provided, to check if the new instance actually represents different information.
The most efficient way to trigger a repaint is to either:
- Extend this class and supply a
repaint
argument to the constructor of the CustomPainter, where that object notifies its listeners when it is time to repaint. - Extend Listenable (e.g. via ChangeNotifier) and implement CustomPainter, so that the object itself provides the notifications directly.
In either case, the CustomPaint widget or RenderCustomPaint render object will listen to the Listenable and repaint whenever the animation ticks, avoiding both the build and layout phases of the pipeline.
The hitTest method is called when the user interacts with the underlying render object, to determine if the user hit the object or missed it.
The semanticsBuilder is called whenever the custom object needs to rebuild its semantics information.
The shouldRebuildSemantics method is called when a new instance of the class is provided, to check if the new instance contains different information that affects the semantics tree.
class Sky extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
final Rect rect = Offset.zero & size;
const RadialGradient gradient = RadialGradient(
center: Alignment(0.7, -0.6),
radius: 0.2,
colors: <Color>[Color(0xFFFFFF00), Color(0xFF0099FF)],
stops: <double>[0.4, 1.0],
);
canvas.drawRect(
rect,
Paint()..shader = gradient.createShader(rect),
);
}
@override
SemanticsBuilderCallback get semanticsBuilder {
return (Size size) {
// Annotate a rectangle containing the picture of the sun
// with the label "Sun". When text to speech feature is enabled on the
// device, a user will be able to locate the sun on this picture by
// touch.
Rect rect = Offset.zero & size;
final double width = size.shortestSide * 0.4;
rect = const Alignment(0.8, -0.9).inscribe(Size(width, width), rect);
return <CustomPainterSemantics>[
CustomPainterSemantics(
rect: rect,
properties: const SemanticsProperties(
label: 'Sun',
textDirection: TextDirection.ltr,
),
),
];
};
}
// Since this Sky painter has no fields, it always paints
// the same thing and semantics information is the same.
// Therefore we return false here. If we had fields (set
// from the constructor) then we would return true if any
// of them differed from the same fields on the oldDelegate.
@override
bool shouldRepaint(Sky oldDelegate) => false;
@override
bool shouldRebuildSemantics(Sky oldDelegate) => false;
}
Composition and the sharing of canvases
Widgets (or rather, render objects) are composited together using a minimum number of Canvases, for performance reasons. As a result, a CustomPainter's Canvas may be the same as that used by other widgets (including other CustomPaint widgets).
This is mostly unnoticeable, except when using unusual BlendModes. For example, trying to use BlendMode.dstOut to "punch a hole" through a previously-drawn image may erase more than was intended, because previous widgets will have been painted onto the same canvas.
To avoid this issue, consider using Canvas.saveLayer and Canvas.restore when using such blend modes. Creating new layers is relatively expensive, however, and should be done sparingly to avoid introducing jank.
See also:
- Canvas, the class that a custom painter uses to paint.
- CustomPaint, the widget that uses CustomPainter, and whose sample
code shows how to use the above
Sky
class. - RadialGradient, whose sample code section shows a different take on the sample code above.
- Inheritance
-
- Object
- Listenable
- CustomPainter
- Implementers
Constructors
- CustomPainter({Listenable? repaint})
-
Creates a custom painter.
const
Properties
- hashCode → int
-
The hash code for this object.
no setterinherited
- runtimeType → Type
-
A representation of the runtime type of the object.
no setterinherited
- semanticsBuilder → SemanticsBuilderCallback?
-
Returns a function that builds semantic information for the picture drawn
by this painter.
no setter
Methods
-
addListener(
VoidCallback listener) → void -
Register a closure to be notified when it is time to repaint.
override
-
hitTest(
Offset position) → bool? - Called whenever a hit test is being performed on an object that is using this custom paint delegate.
-
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
paint(
Canvas canvas, Size size) → void -
Called whenever the object needs to paint. The given Canvas has its
coordinate space configured such that the origin is at the top left of the
box. The area of the box is the size of the
size
argument. -
removeListener(
VoidCallback listener) → void -
Remove a previously registered closure from the list of closures that the
object notifies when it is time to repaint.
override
-
shouldRebuildSemantics(
covariant CustomPainter oldDelegate) → bool - Called whenever a new instance of the custom painter delegate class is provided to the RenderCustomPaint object, or any time that a new CustomPaint object is created with a new instance of the custom painter delegate class (which amounts to the same thing, because the latter is implemented in terms of the former).
-
shouldRepaint(
covariant CustomPainter oldDelegate) → bool - Called whenever a new instance of the custom painter delegate class is provided to the RenderCustomPaint object, or any time that a new CustomPaint object is created with a new instance of the custom painter delegate class (which amounts to the same thing, because the latter is implemented in terms of the former).
-
toString(
) → String -
A string representation of this object.
override
Operators
-
operator ==(
Object other) → bool -
The equality operator.
inherited