Describe CustomPaint and CustomPainter and implement a circle
This tests Flutter's render delegation. Separate CustomPaint, the canvas widget, from CustomPainter, the drawing logic; cover canvas.drawCircle and shouldRepaint returning false. Red flags: calling setState in paint or ignoring shouldRepaint.
WHAT THIS TESTS: This question checks whether you understand the boundary between Flutter's widget layer and its underlying render layer. CustomPaint is a SingleChildRenderObjectWidget, not just a convenience wrapper, and CustomPainter is the delegate that holds the actual drawing instructions. Interviewers want to see that you know who owns the canvas, who owns the lifecycle, and how to avoid frame violations.
A GOOD ANSWER COVERS: First, the roles. CustomPaint is the widget that provides the Canvas during the paint phase, sizes itself to its child if one exists or to the provided size otherwise, and orchestrates two painters: painter draws before the child, and foregroundPainter draws after. CustomPainter is the abstract class you subclass to encapsulate drawing logic; it is stateless and reusable. Second, the implementation. In paint, you receive a Canvas and a Size. To draw a circle, you create a Paint object, set its color and style, and call canvas.drawCircle with an Offset like Offset(size.width / 2, size.height / 2) and a radius. In shouldRepaint, you compare the current instance with the old delegate; if no properties changed, return false so Flutter skips repainting, otherwise return true. Third, mention that the coordinate system starts at the origin and spans the given size, so drawing outside those bounds is undefined behavior unless you wrap the widget with a ClipRect.
COMMON WRONG ANSWERS: A major red flag is saying you would call setState or markNeedsLayout inside the paint method. The layout for this frame has already happened, so mutating state there crashes or corrupts the frame. Another red flag is treating shouldRepaint as unimportant boilerplate and always returning true; that defeats the compositor's raster cache and wastes GPU time. Candidates also sometimes confuse CustomPaint with a generic Container or assume it automatically clips, which it does not.
LIKELY FOLLOW-UPS: The interviewer might ask how you would animate this circle. The correct path is to drive an AnimationController in the widget and pass the current value into the CustomPainter constructor; shouldRepaint then returns true when the animation value changes. They might also ask about isComplex and willChange, which are hints to the raster cache: set isComplex to true for elaborate paths and willChange to true if the picture is expected to change every frame. Another follow-up is how to hit-test a custom shape, which requires overriding hitTest in the CustomPainter.
ONE CONCRETE EXAMPLE: Imagine a Sky painter that fills a blue circle behind text. The CustomPaint widget wraps a Center child containing a Text widget. The Sky painter implements paint by creating a Paint with color Color 0xFF87CEEB and calling canvas.drawCircle with Offset zero and radius 150. shouldRepaint returns false because Sky has no configurable properties. If you later add a radius field to Sky, shouldRepaint compares oldDelegate.radius != radius and returns the result.
Read the original → api.flutter.dev
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.