Animations in Flutter
Animations are one of the essential things that enhances the user experience, makes your application more interactive and makes your users excited to use the application.
I was looking for my next topic to write for Flutter, then I saw this article about motion, usability, and animations and decided to create some of the animations described there with Flutter.
In the scope of this article, we will cover:
- Easing
- Offset & Delay
- Parenting
- Transformation
- Value change
- Masking
If you are ready, let’s get started!
p.s. This article considers that you have a basic understanding about Flutter widgets and working environment.
Small intro to the animation components
Before we dive into the code, we need to cover some components. The first component is called Animation
. Animation object is the object that gets the values that are given and translates those to meaningful animations. Since it’s not bound to any view on the screen, it is unaware of what is happening on the screen. But it has listeners to check out the state of the animation during each frame change.
T second component is called AnimationController
. AnimationController class is the class to control the animation objects. We are using it to start the animation objects, give them durations and many more.
Next component is called Tween
. Tween is a stateless object which only does the mapping from an input range to an output range. Normally the range of AnimationController is 0 to 1. For changing it, we are using Tween objects.
Another component we will be talking about is called Transition
. This is a special widget that applies a transition before painting the child widget.
The last component we will be covering is called AnimatedBuilder
. It creates a widget that can be animated with animation objects and controllers.
Easing Animation
We will start with the easing animation, the animation will bring a shape from the outer screen and leave the screen after waiting for a second. After animation finishes, the screen will be closed.
Let’s start by adding a stateful widget.
After that, we will create the Animation
and the AnimationController
object. We will initialise, these variables at theinitState
method of State
class so, they will be ready to use when the widget is created.
In the initState
method, first, we created an AnimationController
which states that animation will take 2 seconds. There is also a new variable called vsync
. It is the ticker provider which we provide above with with TickerProviderStateMixin
code snippet. Ticker
is the class to notify the animation in each frame change.
The second object that we created in initState
is our Animation
object. First, we define the Tween
object. That tween object states the animated object will come from the left side of the screen and stay in the middle but it’s not what we want (obviously).
In the build
method, we are creating an AnimatedBuilder
. It takes two variables as parameters. One is animation and we will pass our animation controller object there and the other is the builder, which we will be passing a widget. Since we want it to animate, we will be using Transform
object as a base widget. It also takes two variables as parameters, one is transform
and the other one is the child
which will be transformed.
For thechild
, we are passing a simple black square. For transform
we are using Matrix4.translationValues(_animation.value * width, 0.0, 0.0)
snippet. translationValues
method gets x,y,z direction values and transforms the view according to given value (long sentence to handle, I know). In our case, we are getting the screen width and tween variable and transform our view in each frame change to the related position.
Lastly, we have a dispose
method. When the view is disposed, we should release the controller resources to prevent leaks.
But when you call this widget and run the method you will be seeing that, it’s not working. Because you have not started your animation yet. For starting the animation, you are expected to call _controller.forward()
in the place that you want to start it. In our case, it will be at build
method. When you add it there, you will see that there is a square coming to the center of the screen but, do nothing more. For keep doing that, we need something called statusListeners
.
Status listeners can give you information about status when it’s completed or reversed etc. What we will be doing here is, add a status listener and remove it when the animation completed, so it can start another animation. When the second animation stops, our screen will be closed and go back to the previous screen (or close the application in case you only have one widget).
If you update your initState
method as it is above, you would be able to see a black box coming from left side of the screen, stays in the middle and leaves the screen from the right side.
Let’s show the GIF for the first one, we will have an overview video of all the animations that we implemented, at the end of the post.
We managed to the hard part. Rest of it, will be using the animations that we already know.
Offset & Delay Animation
For the offset and delay animation, we will be using most of the code that we created above. Difference will be, we will apply those animations to three different elements and one will be doing it with a delay.
For achieving this goal, we will be using a class called Interval
. Interval is a class that can return a Curve
object to CurvedAnimation
. Interval is getting two important parameters. One is called begin
other is called end
. For Interval’s beginning of the project is 0.0
and end is 1.0
so you can pass two variables between these values to tell the animations to start in that exact point.
For the late animated view, we will create another animation
object with an interval
. Other two views will be using the previous animations that we created. We will also add callback part for the interval view, in the handler
method that we created earlier.
We added a new animation with status handler. All we need to do is, call the animation object as we did in the previous example in an Transform
object. Rest will be handled by the Flutter framework.
We are ready with this one too. Let’s proceed to the parenting animation.
Parenting Animation
In the parenting animation, we start of with two rectangles, one is small and the other one is big. We will be moving two of the rectangles to the center of the screen from the left border of the screen. Meanwhile we are moving it, we will be making the small rectangle as big as the big rectangle.
For starters, we will create an animation object to handle the growing animation. This animation will change the height and width of the view.
Another thing that we will be covering is a method comes from AnimationController. It is called reverse
. This reverses the animation and it has it’s own status from status listener which is calleddismissed
. We will use it to exit the screen when the reverse operation is finished.
For the moving animation, we will use the animation that we defined before. But we will change the animation value to -0.25 to start from the edge of the screen. At the end, our animation widget will look like this.
Transformation/Masking Animation
We will be handling transformation and masking animation together because in both we will be using the same animation. Only difference is in the masking animation, we will be putting a view to be masked by using Stack
.
Since we are masking a square view, we can define a transforming animation which can handle both height and width. Also, for creating a circle in the beginning, we can give a border radius as begin
value in a BorderRadiusTween
and end
value 0 to make it a rectangle.
In code our initState
method will look like as follows.
When we create the views with animation information above, it will be doing the transition in to the height and width of the element to be masked.
We can proceed to the last one now.
Value Change Animation
Value change animation is one of the easy ones that can be implemented. There is a tween called IntTween
and we can directly read the value by calling it. You can simply create a tween element by calling IntTween(begin: 0, end: 10)
and assign begin and end values as the values that you want to have.
Conclusion
That was a lot of information and code to handle at once. But believe me, if you are into Flutter and if you are planning to develop applications using this platform this blog post will be useful for you.
Here is how the latest product looks like:
And you may see the code for the project above.
That was all for the blog post. Looking forward to next blog post!