What you might not know about Custom Views in Flutter.

2 Things to take care of with the CustomPaint Widget

Flutter Community
Published in
4 min readJun 16, 2020

--

I decided to try out flutter and implement one of my favorite projects for a UI Toolkit, “The Circle.” It starts with just drawing a circle on the screen and then changing its color on tap, there are more steps, each one adding complexity but I’ll focus on these two for now to discuss something interesting.

If I were doing something similar on Android, I’d just draw a circle on the canvas in a CustomView. Being an amateur in flutter, I looked up for an equivalent API in flutter, and there is one, the CustomPainter.

Let’s look into some things which I found are easy to miss but very important to be aware of.

1. The View Bounds

So I created DrawCircle which extends CustomPainter and can draw a circle on the canvas.

Then I created a custom widget Circle and internally it returned a CustomPaint object.

This code is just a snippet, you can check out the full code in the repository linked at the end. And it worked!

Circle created using the CustomPaint Widget with our CustomPainter implementation.

Then onto the next job, changing the color on click, again, a quick google search led me to the GestureDetector, and given flutter’s compositive nature, it was reasonably easy to implement it.

Based on the code written, the method onCircleTapped should be triggered when I tapped the circle … but it is not 😟

So I looked at flutter inspector, and this is what I found. The Circle widget has zero height and width … and thus no bounds.

a: Screenshot with Debug Paint turned ON — no bounds around the circle, b: Screenshot from flutter inspector — height and width of the circle is zero

This is the first takeaway,

While using CustomPainter, make sure you give it the correct size so that it can give create bounds for the view. This directly affects interactions with user and other views in the layout.

So I modified the CustomPaint with a size and guess what, the bounds showed up, and clicks started working.

a: Screenshot with Debug paint turned ON — the circle has bounds, b: Screen recording — Circle is detecting taps and changing colors

2. Enforcing the bounds

But there’s one more thing, what if I give it particular size, but try to paint something which will take more area than what I defined 🤔.

And there’s another problem. The drawing can go beyond the bounds, which can be an issue where multiple widgets on a screen maintained by a team. A widget should only be able to work within the bounds it is given and not affect what’s outside in any way. Also, you can see that the circle is not centered because alignment works based on the actual bounds, which are centered 🤷🏻‍♂️.

The second takeaway,

Wrap your CustomPaint in a `ClipRect` widget. What this will do is prevent the drawing from flowing out of the its bounds.

Here’s the change I had to make in Circle

Circle Clipped using ClipRect

And voila! CustomPainter can only draw inside the bounds now. Even if it tried to cross them, it’d be clipped. This will make sure that even if you make a mistake in the calculation while drawing, this widget might look messed up, but it won’t affect other widgets on the screen.

So, those were the two things you should take care of while using CustomPaint in flutter. In the final version, I ended up using ClipOval, better suited for the circle use-case and fixed the circle dimensions. You can check out the full code in this repository.

Also, this was my first time writing about flutter, and I definitely plan to experiment more and share it with everyone.

Until the next one, Stay safe and stay indoors. Ciao!

https://www.twitter.com/FlutterComm

--

--