In this tutorial series, we are going to learn all about Flutter Animations, starting from what is and how to use an
AnimationController, then moving to improve our code with
AnimatedBuilder, and finishing by integrating Flutter packages to simplify and reduce the boilerplate in our code (simple_animations and animator).
Flutter Animations is a really wide topic. Animations in general are one of the building blocks that make an application a delight to use and interact with. Albeit Animations can really make an application shine, they are usually neglected or postpone to later phases or releases, mainly because they do not contribute to the core functionality of the app. Because of that, how to implement Animations in your app is usually one of the last concepts that you will learn in Flutter. Let’s dive in and add some fancy animations to our app!
What is an animation in Flutter
Generally speaking, animations are attributes of a widget that changes in a certain period of time using a specific curve. The value is updated at each frame (usually 60 or more frames per second) which causes the impression of movement.
A curve controls how the animation changes the value of the animated object. For instance, by customizing the curve we can make the animation slower at the beginning (
easeIn), slower at the end (
easeOut), or both (
What does it mean changing the value of the animation? Let’s see an example. If we use
Transform.scale() to animate the size of a
Container, what happens is that the scale factor grows frame by frame until it reaches the target value. What a curve does is changing the way the values are updated on each frame.
For instance, if initially the scale value is 1.0 and at the end of the animation it becomes 3.0, with a linear curve the value will change equally at each step, as represented below.
I/flutter ( 4998): 1.0 I/flutter ( 4998): 1.0 I/flutter ( 4998): 1.18603 I/flutter ( 4998): 1.37212 I/flutter ( 4998): 1.5316 I/flutter ( 4998): 1.7124199999999998 I/flutter ( 4998): 1.89187 I/flutter ( 4998): 2.07219 I/flutter ( 4998): 2.2584 I/flutter ( 4998): 2.61752 I/flutter ( 4998): 2.80741 I/flutter ( 4998): 2.98988 I/flutter ( 4998): 3.0
As you can see, the value grows linearly by more or less 0.2 after each print. If we instead use a
EaseInExponential curve, the output will be way different.
I/flutter ( 4998): 1.0 I/flutter ( 4998): 1.0 I/flutter ( 4998): 1.0094702293851878 I/flutter ( 4998): 1.0193529780954123 I/flutter ( 4998): 1.037860722541809 I/flutter ( 4998): 1.054507356164977 I/flutter ( 4998): 1.0776168376207351 I/flutter ( 4998): 1.11944580078125 I/flutter ( 4998): 1.8622788190841675 I/flutter ( 4998): 2.7412984085083005 I/flutter ( 4998): 3.0
The animation starts really slow, almost static, and then reaches 3.0 super fast.
I really suggest checking out the official Flutter curves documentation. It showcases all the predefined curves available in Flutter, together with a simple animation that explains beautifully how the animation works.
In order to use animations in our app (without any extra package), we need a
StatefulWidget. This widget will contain an
AnimationController object as state. We are going to initialize the
initState() and we need also to dispose it in
Any class that contains an
AnimationController needs to have a
If we only have one AnimationController, then we should use
SingleTickerProviderStateMixin instead of
TickerProviderStateMixin. We add the mixin using the keyword
with of Dart. (Check out the official Dart documentation to learn more about mixins.)
We initialize the
initState() by passing the required
vsync parameter as
this, which references to the class’s ticker mixin that we added before. Adding this parameter will make the animation’s value automatically update on each frame.
We also pass the
duration parameter, which takes a
Duration object that specifies the duration of the animation (in seconds or milliseconds usually, but we are not limited to those two units).
Finally, we start the animation by calling
_controller.forward() at the end of
setState, Rebuilding the UI
AnimationController is itself an
Animation of double, with value that goes from 0.0 to 1.0. We can therefore use it directly if all we need are values between 0 and 1 (like opacity for example). The controller has a
value attribute that contains the value of the animation. We are going to use this value by adding
_controller.value inside our build function to animate our widgets.
Although the value itself is changing, the widget does not rebuild because we are not calling
setState(). If we do not call
setState() in a
StatefulWidget, the variable value will change, but the framework will never call the
build() method and the UI will remain the same. In order to make the animation work, we need to call
setState() after each update of the animation value. We add a listener function on the controller using the
_controller.addListener() method, which is called on each tick/frame of the application. Inside the listener, we call
setState() with and empty body.
Now we can launch the application and see our animation in action! We basically created a fade-in animation. The opacity of the container changes from 0 (invisible) to 1 (fully visible) in the time specified by the duration attribute.
You made it, you just created your first animation in Flutter! That is the most basic and crude method to create animations in Flutter. We are basically using only an
AnimationController and its value. We specify a duration, we pass the
vsync attribute from the Ticker mixin, and we call
setState() from the listener.
You can now experiment using this method. Try to change the type of animation, for example modifying the size of the Container or the position.
Note: This is the most basic and naive method to use animations in Flutter. Generally speaking, it is considered bad practice to call setState directly in a response to an AnimationController changing. In the next parts of the series, we are going to learn about better ways to handle animations such as
AnimatedBuilder. (Thanks to Simon Lightfoot for his suggestion on Twitter)
That’s it for the first part of this Flutter animations series. In the next article we are going to learn everything about
In the meantime, if you are interested in more Flutter articles and tutorials, check out other Flutter articles on my blog.
If you would like to stay updated about future articles, reviews, and tutorials, consider subscribing to my newsletter here blow.
Thanks for reading.