Flutter Animations
The Flutter animation framework provides a layered architecture for controlling motion. At its core, the framework categorizes animations into implicit transitions, explicit controller-driven animations, and physics-based simulations.
Implicit animations
Section titled “Implicit animations”Implicit animations automatically interpolate between a current value and a new target value over a specified duration. The framework calculates intermediate frames when a property changes and the widget rebuilds.
AnimatedContainer is a versatile implicit widget that can animate changes to
size, color, padding, and alignment simultaneously:
The underlying architecture relies on ImplicitlyAnimatedWidget. When the
widget’s configuration changes (detected in didUpdateWidget), the state reuses
its internal AnimationController, rebases the tween’s begin to the current
animation value, and restarts the transition toward the new target. This is why
implicit animations transition smoothly when interrupted mid-flight.
Non-linear interpolation (curves)
Section titled “Non-linear interpolation (curves)”By default, animations transition linearly. Applying a Curve modifies the
interpolation rate. The framework provides standard curves via the Curves
class, such as Curves.easeIn, Curves.bounceOut, and Curves.elasticInOut.
You can also define custom mathematical curves by subclassing Curve and
overriding the transformInternal method.
Explicit animations
Section titled “Explicit animations”Explicit animations require manual lifecycle management using an
AnimationController. This approach is necessary for looping animations,
sequenced transitions, and animations triggered by gesture events.
graph TD
T["TickerProvider<br>(vsync)"] -->|Tick per frame| C["AnimationController<br>(0.0 to 1.0)"]
C -->|Linear Value| A["CurvedAnimation<br>(Non-linear timing)"]
A -->|Eased Value| TW["Tween<br>(Maps to target data type)"]
TW -->|Output Value| W["AnimatedBuilder<br>(Rebuilds UI)"]
style T fill:#e1f5fe,stroke:#03a9f4,stroke-width:2px,color:#000
style C fill:#e8f5e9,stroke:#4caf50,stroke-width:2px,color:#000
style A fill:#fff3e0,stroke:#ff9800,stroke-width:2px,color:#000
style TW fill:#fce4ec,stroke:#e91e63,stroke-width:2px,color:#000
style W fill:#f3e5f5,stroke:#9c27b0,stroke-width:2px,color:#000
Animation controllers and vsync
Section titled “Animation controllers and vsync”An AnimationController generates a new value whenever the hardware is ready
for a new frame. To prevent off-screen computations and synchronize with the
device refresh rate, the controller requires a TickerProvider (passed via the
vsync argument).
When managing multiple controllers in a single widget, use
TickerProviderStateMixin instead of SingleTickerProviderStateMixin.
Tweens and mapping
Section titled “Tweens and mapping”A controller typically outputs values between 0.0 and 1.0. A Tween maps
this unit interval to a required data type (such as Offset or double). For
types that lack arithmetic operators, use a dedicated subclass: ColorTween for
colors, RectTween for rectangles, and so on.
Rebuilding the UI
Section titled “Rebuilding the UI”To apply the animation to the render tree, use an AnimatedBuilder or subclass
AnimatedWidget. This localized rebuilding prevents the entire widget tree from
refreshing on every frame.
Alternatively, TweenAnimationBuilder provides a declarative API that does not
require a manually managed AnimationController. Whenever the tween’s end
value changes, the widget re-animates from the current value toward the new
target, making it well-suited for driven transitions and entrance animations
where that retargeting behavior is desirable.
Physics-based simulations
Section titled “Physics-based simulations”For animations that must react naturally to user input (such as a scroll view snapping into place), use the physics simulation engine rather than fixed-duration controllers.
The AnimationController can execute a Simulation using
controller.animateWith(Simulation). The framework provides several standard
physics models:
SpringSimulation: Models tension and friction.GravitySimulation: Models gravitational acceleration.FrictionSimulation: Models gradual deceleration.
Third-party vector animations
Section titled “Third-party vector animations”For complex vector graphics and state-machine animations, use third-party formats rather than the built-in widget framework:
- Lottie: Uses animations exported as JSON from Adobe After Effects. Best for predetermined, timeline-based animations.
- Rive: Uses interactive state machines designed for real-time manipulation. Best for dynamic assets requiring programmatic state changes.
Performance considerations
Section titled “Performance considerations”Modifying properties that affect layout (such as width, height, or
padding) forces the framework to recalculate geometry on every frame, which
can cause dropped frames.
To optimize performance, animate properties that are applied during the paint phase, which avoids rebuilds and layout recalculation:
- Opacity: Use
FadeTransitionorAnimatedOpacity. - Transform: Use
RotationTransition,ScaleTransition, orSlideTransition.
When using AnimatedBuilder, always pass static child widgets via the child
parameter. This prevents the framework from recreating the child subtree during
every animation tick.
For complex subtrees that animate independently from the rest of the screen,
wrap them in a RepaintBoundary. This isolates the subtree into its own layer,
so its repaints do not propagate to the rest of the tree.