What you might not know about Custom Views in Flutter.
2 Things to take care of with the CustomPaint Widget
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!
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.
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.
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
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!