CustomPaint is a Flutter widget that allows developers to draw custom shapes, visuals, and effects directly on a canvas. It is used when standard widgets are not flexible enough to represent a specific visual requirement.
CustomPaint is commonly applied in advanced UI scenarios such as:
CustomPaint unlocks full control over rendering. It allows teams to implement visuals that would otherwise require complex widget trees or platform-specific code.
For performance-critical or visually unique components, CustomPaint often results in simpler and more efficient implementations than composing many small widgets.
CustomPaint delegates rendering to a CustomPainter class. This class receives a Canvas object and a Size, which together define the drawing surface.
Inside the painter, drawing is performed imperatively using low-level operations such as drawing lines, paths, circles, and shapes. Flutter calls the paint method whenever the widget needs to be redrawn.
The framework also relies on the shouldRepaint method to decide whether a repaint is necessary, which makes CustomPaint efficient when implemented correctly.
A simple example of drawing a circle:
class CirclePainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
final paint = Paint()
..color = Colors.blue
..style = PaintingStyle.fill;
canvas.drawCircle(
size.center(Offset.zero),
size.width / 2,
paint,
);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return false;
}
}Usage in a widget:
CustomPaint(
size: const Size(40, 40),
painter: CirclePainter(),
)This pattern scales to much more complex visuals while keeping rendering logic isolated from layout.
CustomPaint becomes especially valuable when building highly atomic design systems.
Instead of assembling components from multiple widgets, teams can create low-level visual primitives such as:
This approach keeps components small, predictable, and easy to theme. It also reduces layout complexity, which is important when design systems aim for consistency across many screens.
The trade-off is higher implementation complexity and the need for strong internal conventions.
CustomPaint is useful when an application requires fine-grained control over rendering that standard Flutter widgets cannot provide.
CustomPaint allows developers to draw directly onto a canvas using the paint method of a CustomPainter.
This approach is appropriate when a visual element requires:
These cases may be inefficient or impossible to implement with standard Flutter widgets.
CustomPaint can also be useful when performance is a concern.
If widget composition introduces:
rendering directly on a canvas can reduce overhead and improve frame rates.
This is particularly helpful for reusable visual primitives such as:
CustomPaint is well suited for design systems that require precise visual fidelity.
It allows developers to ensure that every pixel, line, or curve matches the intended specification.
This approach fits best in mature codebases that prioritize:
Examples include complex dashboards, game UI elements, or custom animated widgets.
CustomPaint is not always the right choice and can introduce unnecessary complexity in some situations.
If a design can be implemented using existing Flutter widgets such as:
ContainerStackRowColumnit is usually simpler and more maintainable to use those widgets.
Adding a canvas layer with CustomPaint in these cases increases complexity and can make the code harder to read or debug.
CustomPaint is not well suited for layouts that change frequently based on:
CustomPaint requires developers to manually handle sizing, positioning, and drawing logic. For dynamic interfaces, standard widgets with built-in layout behavior provide a more predictable solution.
Teams with limited experience in canvas-based rendering should avoid using CustomPaint for routine tasks.
Errors in:
can introduce subtle visual bugs and create long-term maintenance challenges. Overusing CustomPaint in simple scenarios may make the codebase more fragile without providing meaningful benefits.
Typical mistakes when using CustomPaint include:
shouldRepaint logic.CustomPainter should focus purely on rendering, not state or interaction handling.
When working with CustomPaint:
shouldRepaint correctly.15 min. • Jun 6, 2023
Flutter is known for its seamless UI/UX features and robust design elements. It allowed us to deliver a unique customer experience in the “CA24 Mobile” banking app. This article shares some of the learnings and pain points behind implementing it in this large project.
9 min. • Jun 1, 2023
Building a new digital product, such as a web or mobile application, is complex. You need to map user stories - create a simple description of features - then apply them to the developers' scope of work and the app’s design. Discover how a design system can unleash efficiency, consistency, and scalability in your digital product.
5 min • Aug 6, 2020
Whiteboards make it easier to collaborate on designs, teach people new concepts, and express ideas. In this blog post, we explore a possible implementation of a whiteboard using Flutter to create a mobile application and Firestore database as backend.