Flutter — Animation overviews
How to choose which Flutter animation is right for you?

Adding some animations to the app makes it more smooth, and improves the user experience. However, it sometimes confuses us that which approach should we take to achieve the animation. Today, we’re going to figure out the right way for us. In this post, you’ll see a series of questions that will help you determine what kind of solution should be used.
Basically, this post refers to this video from the Flutter team. Before we get started, I strongly recommend you to watch this amazing video.
Table of contents
- Drawing-based animations or Code-based animations
- Code-based: Implicit Animation or Explicit Animation
- Implicit Animation
- Explicit Animation
- CustomPainter
- Summary and difficulty
1. Drawing-based animations or Code-based animations
Is it like a drawing?
The first question to decide which way to use is to ask yourself: Is it like a drawing? For example, the following GIF is definitely a customized animation created by ourselves or the design team.

or it seems difficult to approach by code like

Then the answer would be yes.
So, if your answer is…
Yes — Drawing-based animations
The Flutter team recommends us use the 3rd party packages, like Flare, Lottie, or other packages. We can easily implement the animation provided by the design team. For the details, I’ll write in the other posts. Stay tuned.
No — Code-based animations
We can make some mutations on widgets like changing color, position, rotation, etc. It is faster and intuitive to write it by code directly. Basically, code-based animations could be divided into implicit animation
and explicit animation
.
2. Code-based: Implicit Animation or Explicit Animation
Okay, now we know we need a code-based animation. Then there are three questions to ask ourselves to determine which type of animation we need, implicit animation
or explicit animation
.
Does it repeat “forever”?
The answer is yes when the animation needs to keep playing while on a certain screen or a certain condition is true, such as music playing.
Is it “discontinuous”?
The answer is yes when the animation is discontinuous. For example,

The square grows from small to large, it never shrinks back from large to small again. Then we can say it is discontinuous.
Do multiple widgets animate together?
The answer is yes when multiple widgets are animating in a coordinated fashion together.

If your answer is yes to any of those three questions, then you should use explicit animation
; Otherwise, use implicit animation
.
3. Code-based: Implicit Animation
The implicit animation could be divided into built-in widgets and customized widgets.
3.1. Built-in implicit animation widgets

ImplicitAnimtatedWidget
is an abstract class for building widgets that animate changes to their properties. A number of implicitly animated widgets ship with the framework. They are usually named AnimatedFoo
:
- TweenAnimationBuilder, which animates any property expressed by a Tween to a specified target value.
- AnimatedAlign, which is an implicitly animated version of Align.
- AnimatedContainer, which is an implicitly animated version of Container.
- AnimatedDefaultTextStyle, which is an implicitly animated version of DefaultTextStyle.
- AnimatedOpacity, which is an implicitly animated version of Opacity.
- AnimatedPadding, which is an implicitly animated version of Padding.
- AnimatedPhysicalModel, which is an implicitly animated version of PhysicalModel.
- AnimatedPositioned, which is an implicitly animated version of Positioned.
- AnimatedPositionedDirectional, which is an implicitly animated version of PositionedDirectional.
- AnimatedTheme, which is an implicitly animated version of Theme.
- AnimatedCrossFade, which cross-fades between two given children and animates itself between their sizes.
- AnimatedSize, which automatically transitions its size over a given duration.
- AnimatedSwitcher, which fades from one widget to another.
These widgets are simple and don’t require us to manually manage the lifecycle of an AnimationController. We can just change the value and rebuild the widget, and then the animation happens. Here is an example of one of the animated widget, AnimatedContainer
:

Whenever users click the container, we rebuild the widget by invoking setState()
, and the values such as the size, color of the container would be changed with animation. This is really convenient that we don’t need to care about any detail of the animation, but only telling what’s the next style of the widget we want.
Moreover, ImplicitAnimtatedWidget
also allows us to assign some parameters.
- Curve:
The official document is very clear and sweet that they show all the built-in curve behaviors in videos. So if you want to change the animation curve, just pick what you want. - duration:
This literally means the duration of the animation. It can be days, hours, minutes, seconds, milliseconds, even microseconds. - onEnd:
We can do something after the animation finishes.
3.2. TweenAnimationBuilder

If we cannot find a proper animation in built-in implicit animation, we can create our own animation by using TweenAnimationBuilder
. TweenAnimationBuilder
also inherits from ImplicitlyAnimationWidget
. We could provide the begin and end values and create our own widget in builder
, then the TweenAnimationBuilder
will take care of everything and present an awesome animation.

4. Code-based: Explicit Animation
Explicit animation means the animation starts when explicitly asked to. It requires an AnimationController, which allows us to
- Play an animation forward or in reverse, or stop an animation.
- Set the animation to a specific value.
- Define the upperBound and lowerBound values of an animation.
- Create a fling animation effect using a physics simulation.
Life cycle
We need to handle the life cycle of the animation controller, which means it should be disposed when it is no longer used. Basically, we can create it in State.initState and dispose it in State.dispose with a StatefulWidget.
AnimationController _animationController;@override
void initState() {
super.initState();
_animationController = AnimationController(...)
}@override
void dispose() {
super.dispose();
_animationController.dispose();
}
Just like implicit animation widgets, explicit animation widgets could be divided into built-in widgets and customized widgets as well.
4.1. Built-in explicit animation

AnimatedWidget
is an abstract class which rebuilds when the given Listenable changes value. It can be used with any Listenable
, most common is Animation, but it also can be ChangeNotifier and ValueNotifier.
A number of animated widgets ship with the framework. They are usually named FooTransition
.
- AnimatedBuilder, which is useful for complex animation use cases and a notable exception to the naming scheme of AnimatedWidget subclasses.
- AlignTransition, which is an animated version of Align.
- DecoratedBoxTransition, which is an animated version of DecoratedBox.
- DefaultTextStyleTransition, which is an animated version of DefaultTextStyle.
- PositionedTransition, which is an animated version of Positioned.
- RelativePositionedTransition, which is an animated version of Positioned.
- RotationTransition, which animates the rotation of a widget.
- ScaleTransition, which animates the scale of a widget.
- SizeTransition, which animates its own size.
- SlideTransition, which animates the position of a widget relative to its normal position.
- FadeTransition, which is an animated version of Opacity.
- AnimatedModalBarrier, which is an animated version of ModalBarrier.
Take RotationTransition
for example,
All we need to do is creating an AnimationController
and a widget, then put them into a RotationTransition
. You can see the widget begins to rotate.

4.2. Custom explicit animation
If the built-in widgets don’t meet your needs, you can probably create it by yourself. And there are two ways for it, but both can achieve what we want. It’s all just a matter of taste. So before doing it, ask yourself:
Do I want my animation to be a standalone widget or part of another surrounding widget?
- Standalone widget
you can create your custom widget by extendingAnimatedWidget
- Surrounding widget: AnimatedBuilder
Or you can wrap your widget with AnimationBuilder
.

5. CustomPainter
CustomPainter
is used for an extremely custom effect or saving on performance. We can draw directly on the canvas. But do care that it may cause other performance issues if we draw the painting in an inappropriate way. If you’re interested in that, check out this video:
6. Summary and difficulty

The Flutter team provides a flow chart of all the steps mentioned above. We can determine which approach is the best for us by going through the questions quickly.
Difficulty

There’s one more thing I’d like to mention is the difficulty of all the solutions. As we can see, the complexity is
ImplicitAnimatedWidgets
<ExplicitAnimatedWidgets
<CustomPainter
.- Built-in widgets < Customized widgets.
So when you start to decide which way to use, please also consider the complexity. It would be helpful to evaluate how long will it take to implement the animation.
That’s all for today. Hope this post helps you know more about the animations. If you have any questions or suggestions, please comment below to let me know. I am glad to discuss this more with you guys. Thanks for your time reading the post, see you next time. ✋✋