Percentage ring animation with Flutter

Easily create a stateless animated ring widget

Mobile@Exxeta
3 min readSep 12, 2023

Visualizing data makes it easier to explore and understand; by using animations, you can build smooth transitions to make dynamic data appear even more dynamic.

In this story, we’ll show you how to build a stateless Flutter widget that animates a percentage of a ring. To demonstrate this, we created a small app that animates a ring arc based on the value of an input field. However, the following steps only cover the topic of how to build the animated ring widget.

Ring Animation Demo

Drawing an Arc

First, to be able to draw only a part of a ring, we create a class called ArcPainter that extends the abstract class CustomPainter.

We define three variables to be able to pass the color, the radius, and the filling level in percent the ring should have.
Because we are extending the CustomPainter, we must override the paint() and shouldRepaint() methods.
For shouldRepaint(), we return true to repaint the ring whenever the value of a passed property changes.

Define the paint() method

With the following code inside the paint() method, we define what the ArcPainter should paint:

To be able to draw only a part of a ring, we use the drawArc() method. For this, we specify the rectangle that the ring must be painted inside and the start point. Since we already imported Dart’s math package in the first code snippet, we can utilize pi.
By calculating the radian with the given percentage, we define the end point of the arc. We instantiate Paint() with some styling, like the color and the width of the stroke.
We change the painter’s style to PaintingStyle.stroke as we only want to draw a ring and not the entire circle.
Setting the stroke cap to StrokeCap.round is just a personal preference.
The useCenter property of drawArc() is set to false, but if you want to draw a pie chart, set it to true.

Using the ArcPainter

Next, we want to build a ring widget that stacks two ArcPainters, of which the lower one draws a complete and the upper one a partial ring.

We create a stateless widget called AnimatedRing with the same three properties as the ArcPainter. This widget builds a SizedBox of the width and height double its given radius property.
Inside this SizedBox, we stack two CustomPainters with our ArcPainter class as painter. Where both of them get the radius passed, the first one uses the color with opacity and only the second painter uses the fillPercentage.

Adding animation

Animating the widget is super simple by just putting a TweenAnimationBuilder around the second of the two CustomPainters.

We pass a tween that begins with 0.1 (to indicate a small piece of the arc) and ends within the given duration at the passed fillPercentage.
Finally, we change the ArcPainter’s percentage property to the value given by the animation builder.

Conclusion

Within only three steps, you can easily create a percentage ring animation widget. And the best part is that you don’t need to use a stateful widget. Just create a custom arc painter and build it with the help of a TweenAnimationBuilder to animate it.
If you have any questions, don’t hesitate to contact us.

Have fun coding! (by Luisa Fröhlich)

--

--

Mobile@Exxeta

Passionate people @ Exxeta. Various topics around building great solutions for mobile devices. We enjoy: creating | sharing | exchanging. mobile@exxeta.com