Animate Radial Menu

Ankit Gupta
3 min readNov 2, 2020


So today we are going to craft our widget by using Custom Clipper in Flutter.

And now it's time to look at our task.

Today we need an extra package called Flutter_toggle_animated.

This is my first published package it aims to reduce the process of initializing animation with just a single line and worry only about animation playing forward and reverse. You may use this as this hides our complex listeners and results in keeping our initState clean and short.

It's as simple as

controller = ToggleController( vsync: this, animationDuration: const Duration(milliseconds: 1200)); 

and we are ready to animate.

So here our basic idea is to create a rect and then Clip this using widget ClipOval which takes CustomClipper which we are going to define using some trigonometry.

ClipOval takes an argument clipper, for this we need to create our own custom clipper by Extending our class ProgressCircleClipper to CustomClipper<T> where T is a generic type of Rect (for our implementation).

class ProgressCircleClipper extends CustomClipper<Rect> {  
final double currentProgress; ProgressCircleClipper({this.currentProgress});
Rect getClip(Size size) {
// getting point of origin for our angle
final pointStart = Offset(size.width, size.height);
// calculate our angle
double theta = atan(pointStart.dy / pointStart.dx);
// radius
final topmostEnd = pointStart.dy / sin(theta);
//calculating radius with animation progress
final radius = topmostEnd * currentProgress;
final diameter = 2 * radius;
return Rect.fromLTWH( pointStart.dx - topmostEnd , pointStart.dy - topmostEnd , diameter, diameter);
bool shouldReclip(CustomClipper<Rect> oldClipper) {
return true;

here in the above class, we need to make this accept a parameter current progress which is our latest animation value.

and now if you are confused about some calculation, so let’s take a look,

So here pointStart of our calculation is (0,0).

We are going to construct rect large so it actually covers our area with clipper.

And then we calculate the length of the topmost corner of our available container which is Z and our radius ( we may consider the length of y-axis from origin but it would result in creating a semi-circle and our both topmost corner will be out of our clipping for this reason we considered the topmost corner of Z.)

sin θ = Opposite Side/Hypotenuse.
cos θ = Adjacent Side/Hypotenuse.
tan θ = Opposite Side/Adjacent Side.

and finally, we calculate a new radius by multiplying our topMostEnd with current animation progress, so our rect get rendered with every progressive value and achieve our goal.

So with this, we have covered a decent amount of topics on animation and paints and clippers and in our next article let's explore STATE MANAGEMENT.