Math-Driven Approach towards Animation in Flutter
Apps are boring! Only until we add some adorable animations into them. Since Flutter is a UI toolkit for building beautiful apps, we can animate literally everything in the Flutter. By everything, I meant to say every widget. Because in Flutter, everything is Widgets.
In this blog, I will teach you to build the animations from the very beginning in the Flutter. One of the ways to build the animations is to change the value lets say the font size(or any anything) dynamically, and repeatedly calling setState in a StatefulWidget.
Let us start building the animations…
We know that animation is just changing the values dynamically and building the widgets multiple times per second. So, let's build some UI first. This UI will contain the Dart logo, Flutter logo, and the “Flutter” text. And all of these three components are placed at the center of the Row.
In the code, you can see that we are using two types of Transforms. The Transform.translate is applied to the Images. The Transform.translate will change the position of its child with respect to the values of the x-axis and y-axis provided by the Offset. The second transform I’m using is the Transform.scale. This transform is applied to the text. This will increase and decrease the size of its child. To change the values dynamically, I’m using the variable named padding.
Now, the question that arises here is how we can change the values dynamically? This is where the animation comes into play.
For achieving the animation, we required to add the AnimationController. To tell the Flutter that there is some animation in this Widget, we have to add the ticker. There are two types of mixin present in the Flutter. One is the SingleTickerProviderStateMixin and another is TickerProviderStateMixin. The SingleTickerProviderStateMixin will take only one AnimationController and TickerProviderStateMixin will take multiple AnimationControllers. As I’m will be using multiple animations on the same screen, I had used TickerProviderStateMixin.
For using the values inside a widget, we need an Animation<double> instance which exposes a value property.
AnimationController takes the Duration and generates the values ranging from 0(start) to 1(end) in the specified time span. To start the animation we have to use the forward method provided by the AnimationController.
We will be implementing the AnimationController in the initState method and providing its values to the Animation<double>. We are using the Tween to change the value range.
This code will dynamically update the values of the variable named padding and calls the setState. This code will check for the status of the Animation. And if the animation is completed then it will reverse the AnimationController and this process will keep on going infinite times. If due to some problem, the animation gets stuck, then it will call the forward method of the AnimationController and will start the animation again.
Finally, as usual, it will call the forward method of the AnimationController to start the animation.
Let us see the animation in the action
Build the app and the animation will look like this.
Now, I want to display a “Welcome” text. This text will automatically rotate in a circular path along with scaling its size all the way from small to large continuously. This text will be placed in a circular container and the color of the container will change continuously.
Let’s build this Widget first and after that, I will add animation to it.
Transform.scale applied to the “welcome” text will be responsible for increasing and decreasing the size of the text. We just have to change the values of the scale parameter of the Transform.scale dynamically. After that, I will place this Transform widget at the center of the circular container. Now, to rotate this circular container, I will apply Transform.rotate transformation. This transform will require the angle by which it will rotate the widget.
To build this animation, we will require another AnimationController.
Also, implement the AnimationController in the initState.
The animation implemented above will be responsible for rotating the circular container. As we know Tween is used to set the range of the values. As we have to rotate the circular container in the full circle, we have to express the values ranging from 0 to 2π(0 to 360 degrees).
Also, we want to change the color of the container dynamically. For this, we have to write a function that will change the color on every build. Let’s name this function as changeColor.
Before moving forward, let me tell you the purpose behind using the sleep function. If we run the changeColor function without the sleep function, then it will change the color of the container so fast that our eyes can’t capture it. To make the color-changing noticeable, I had used a sleep function with a duration of 100 milliseconds.
Now, this function will require a list of colors. So, the last thing we have to do is to define the list of the colors.
If we run this animation, it will look like this.
Let us head to the final part.
In this part, I would like to add animation to the text using the Padding widget. The text on the button will continuously be moving forward repeatedly.
Let’s create a button and add some text to it. We will wrap this text up in the Padding widget and apply some animation to the text using the padding property.
As we did earlier, similarly, we will create a new AnimationController and implement it in the initState.
Implementing the textController in the initState.
We will use the values form the textAnimation and change the values of the padding on every build using the setState.
Getting the Final Animation
Finally, we will build the entire project and the combined effect of the animation will look like this-
We made it! Animations are not that hard if you understand the math behind it.
Animation from scratch This project is a starting point for a Flutter application. A few resources to get you started…
If you think that these animations can further be improved, then feel free to contribute to this repository.