pub trait CustomPainter: 'static {
// Required methods
fn paint(&self, app: &mut App, canvas: &mut Canvas, size: Size);
fn should_repaint(
&self,
app: &App,
old_delegate: &dyn CustomPainter,
) -> bool;
fn as_any(&self) -> &dyn Any;
// Provided methods
fn repaint(&self) -> Option<&Rc<dyn Listenable>> { ... }
fn hit_test(&self, app: &App, position: Offset) -> Option<bool> { ... }
}Expand description
The interface used by CustomPaint (in the widgets library) and
RenderCustomPaint (in the rendering library).
To implement a custom painter, implement this trait to define your custom paint delegate.
A CustomPainter must implement the paint and
should_repaint methods, and may optionally also implement the
hit_test method.
The paint method is called whenever the custom object needs to be
repainted.
The should_repaint 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 supply a repaint
listenable, which notifies its listeners when it is time to repaint: the
RenderCustomPaint listens to it and repaints whenever the animation ticks, avoiding both
the build and layout phases of the pipeline.
The hit_test method is called when the user interacts with the
underlying render object, to determine if the user hit the object or missed it.
§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 blend modes. 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::save_layer and
Canvas::restore when using such blend modes. Creating new layers is
relatively expensive, however, and should be done sparingly to avoid
introducing jank.
Required Methods§
Sourcefn paint(&self, app: &mut App, canvas: &mut Canvas, size: Size)
fn paint(&self, app: &mut App, canvas: &mut Canvas, size: Size)
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.
Paint operations should remain inside the given area. Graphical
operations outside the bounds may be silently ignored, clipped, or not
clipped. It may sometimes be difficult to guarantee that a certain
operation is inside the bounds (e.g., drawing a rectangle whose size is
determined by user inputs). In that case, consider calling
Canvas::clip_rect at the beginning of paint so everything that follows
will be guaranteed to only draw within the clipped area.
Implementations should be wary of correctly pairing any calls to
Canvas::save / Canvas::save_layer and Canvas::restore, otherwise all
subsequent painting on this canvas may be affected, with potentially
hilarious but confusing results.
To paint text on a Canvas, use a TextPainter.
app reaches what a Dart painter reads directly: an animation’s value, the fonts.
Sourcefn should_repaint(&self, app: &App, old_delegate: &dyn CustomPainter) -> bool
fn should_repaint(&self, app: &App, old_delegate: &dyn CustomPainter) -> 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).
If the new instance represents different information than the old instance, then the method should return true, otherwise it should return false.
If the method returns false, then the paint call might be optimized
away.
It’s possible that the paint method will get called even if
should_repaint returns false (e.g. if an ancestor or
descendant needed to be repainted). It’s also possible that the paint
method will get called without should_repaint being called at
all (e.g. if the box changes size).
If a custom delegate has a particularly expensive paint function such that
repaints should be avoided as much as possible, a RepaintBoundary or
crate::RenderRepaintBoundary (or other render object with
RenderObject::is_repaint_boundary set to true) might be helpful.
old_delegate is only ever a painter of this painter’s own type, as Dart’s covariant
parameter is.
Provided Methods§
Sourcefn repaint(&self) -> Option<&Rc<dyn Listenable>>
fn repaint(&self) -> Option<&Rc<dyn Listenable>>
The Listenable that notifies when it is time to repaint.
Dart’s CustomPainter takes it as a constructor argument and forwards addListener /
removeListener to it; here the painter answers with it and the same forwarding is the
Listenable implementation of dyn CustomPainter.
Sourcefn hit_test(&self, app: &App, position: Offset) -> Option<bool>
fn hit_test(&self, app: &App, position: Offset) -> Option<bool>
Called whenever a hit test is being performed on an object that is using this custom paint delegate.
The given point is relative to the same coordinate space as the last
paint call.
The default behavior is to consider all points to be hits for background painters, and no points to be hits for foreground painters.
Return Some(true) if the given position corresponds to a point on the drawn
image that should be considered a “hit”, Some(false) if it corresponds to a
point that should be considered outside the painted image, and None to use
the default behavior.
Trait Implementations§
Source§impl Listenable for dyn CustomPainter
impl Listenable for dyn CustomPainter
Source§fn add_listener(&self, app: &mut App, listener: Listener)
fn add_listener(&self, app: &mut App, listener: Listener)
Register a closure to be notified when it is time to repaint.
Forwards to the repaint listenable, if it is not None.
Source§fn remove_listener(&self, app: &mut App, listener: &Listener)
fn remove_listener(&self, app: &mut App, listener: &Listener)
Remove a previously registered closure from the list of closures that the object notifies when it is time to repaint.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".