Skip to content
Boring Doc
Official documentation (snapshot)doc

Introduction to animations

How to perform animations in Flutter.

Source last updated Oct 21, 2026 · last synchronized 3 weeks ago · commit b3045439b7c0 · read on docs.flutter.dev

This is a rendered snapshot of the official page as stored by Boring Doc for provenance and search. Site-specific components (embedded demos, DartPad, images with relative paths) may not render; use the official page for the full experience. Content © The Flutter Authors, CC BY 3.0.

Well-designed animations make a UI feel more intuitive, contribute to the slick look and feel of a polished app, and improve the user experience. Flutter's animation support makes it easy to implement a variety of animation types. Many widgets, especially Material widgets, come with the standard motion effects defined in their design spec, but it's also possible to customize these effects.

Choosing an approach

There are different approaches you can take when creating animations in Flutter. Which approach is right for you? To help you decide, check out the video, How to choose which Flutter Animation Widget is right for you? (Also published as a companion article.)

(To dive deeper into the decision process, watch the Animations in Flutter done right video, presented at Flutter Europe.)

As shown in the video, the following decision tree helps you decide what approach to use when implementing a Flutter animation:

The animation decision tree

Animation deep dive

For a deeper understanding of how animations work in Flutter, watch Animation deep dive. (Also published as a companion article.)

Implicit and explicit animations

Pre-packaged implicit animations

If a pre-packaged implicit animation (the easiest animation to implement) suits your needs, watch Animation basics with implicit animations. (Also published as a companion article.)

Custom implicit animations

To create a custom implicit animation, watch Creating your own custom implicit animations with TweenAnimationBuilder. (Also published as a companion article.)

Built-in explicit animations

To create an explicit animation (where you control the animation, rather than letting the framework control it), consider using one of the built-in explicit animation classes. To learn more, watch Making your first directional animations with built-in explicit animations. (Also published as a companion article.)

Explicit animations

If you need to build an explicit animation from scratch, watch Creating custom explicit animations with AnimatedBuilder and AnimatedWidget. (Also published as a companion article.)

Animation types

Generally, animations are either tween- or physics-based. The following sections explain what these terms mean, and point you to resources where you can learn more.

Tween animation

Short for in-betweening. In a tween animation, the beginning and ending points are defined, as well as a timeline, and a curve that defines the timing and speed of the transition. The framework calculates how to transition from the beginning point to the end point.

Physics-based animation

In physics-based animation, motion is modeled to resemble real-world behavior. When you toss a ball, for example, where and when it lands depends on how fast it was tossed and how far it was from the ground. Similarly, dropping a ball attached to a spring falls (and bounces) differently than dropping a ball attached to a string.

Common animation patterns

Most UX or motion designers find that certain animation patterns are used repeatedly when designing a UI. This section lists some of the commonly used animation patterns, and tells you where to learn more.

Animated list or grid

This pattern involves animating the addition or removal of elements from a list or grid.

  • AnimatedList example This demo, from the Sample app catalog, shows how to animate adding an element to a list, or removing a selected element. The internal Dart list is synced as the user modifies the list using the plus (+) and minus (-) buttons.

Shared element transition

In this pattern, the user selects an element—often an image—from the page, and the UI animates the selected element to a new page with more detail. In Flutter, you can implement shared element transitions between routes (pages) using the Hero widget.

  • Hero animations How to create two styles of Hero animations:

    • The hero flies from one page to another while changing position and size.
    • The hero's boundary changes shape, from a circle to a square, as it flies from one page to another.
  • Consult the API documentation for the Hero, Navigator, and PageRoute classes.

Staggered animation

Animations that are broken into smaller motions, where some of the motion is delayed. The smaller animations might be sequential, or might partially or completely overlap.

Essential animation concepts and classes

The animation system in Flutter is based on typed Animation objects. Widgets can either incorporate these animations in their build functions directly by reading their current value and listening to their state changes or they can use the animations as the basis of more elaborate animations that they pass along to other widgets.

Animation<double>

In Flutter, an Animation object is independent of what is rendered onscreen. An Animation is an abstract class that exposes its current value and its status: dismissed, forward, reverse, or completed. One of the more commonly used animation types is Animation<double>.

An Animation object sequentially generates interpolated numbers between two values over a certain duration. The output of an Animation object might be linear, a curve, a step function, or any other mapping you can create. Depending on how the Animation object is controlled, it could run in reverse, or even switch directions in the middle.

Animations can also interpolate types other than double, such as Animation<Color> or Animation<Size>.

An Animation object has state. Its current value is always available in the .value getter.

An Animation object doesn't handle rendering or build() functions.

CurvedAnimation

A CurvedAnimation defines the animation's progress as a non-linear curve.

animation = CurvedAnimation(parent: controller, curve: Curves.easeIn);

CurvedAnimation and AnimationController (described in the next sections) are both of type Animation<double>, so you can pass them interchangeably. The CurvedAnimation wraps the object it's modifying—you don't subclass AnimationController to implement a curve.

You can use Curves with CurvedAnimation. The Curves class defines many commonly used curves, or you can create your own by overriding transformInternal(). For example:

import 'dart:math';

class ShakeCurve extends Curve {
  @override
  double transformInternal(double t) => t + sin(t * pi * 4) * 0.2;
}

If you want to apply an animation curve to a Tween, consider using CurveTween.

AnimationController

AnimationController is a special Animation object that generates a new value whenever the hardware is ready for a new frame. By default, an AnimationController linearly produces the numbers from 0.0 to 1.0 during a given duration. For example, this code creates an Animation object, but does not start it running:

controller = AnimationController(
  duration: const Duration(seconds: 2),
  vsync: this,
);

AnimationController derives from Animation<double>, so it can be used wherever an Animation object is needed. However, the AnimationController has additional methods to control the animation. For example, you start an animation with the .forward() method. The generation of numbers is tied to the screen refresh rate (typically 60 to 120 frames per second). After each number is generated, each Animation object calls the attached listener callbacks. To create a custom display list for each child, refer to RepaintBoundary.

When creating an AnimationController, you pass it a vsync argument. The presence of vsync prevents offscreen animations from consuming unnecessary resources. You can use your stateful object as the vsync by adding SingleTickerProviderStateMixin to the class definition. You can find an example of this in animate1 on GitHub.

lowerBound and upperBound (0.0 and 1.0 by default), even when driven by fling().

A CurvedAnimation, however, can exceed the 0.0 to 1.0 range, even if its parent AnimationController doesn't. Depending on the curve selected, the output of the CurvedAnimation can have a wider range than the input. For example, elastic curves such as Curves.elasticIn significantly overshoot or undershoot the default range.

By default, the AnimationController object ranges from 0.0 to 1.0. If you need a different range or a different data type, you can use a Tween to configure an animation to interpolate to a different range or data type. For example, the following Tween goes from -200.0 to 0.0:

tween = Tween&#x3C;double>(begin: -200, end: 0);

A Tween defines a mapping from an input range to an output range. The input range is commonly 0.0 to 1.0, but that's not a requirement.

A Tween inherits from Animatable<T>, not from Animation<T>. An Animatable, like Animation, doesn't have to output double. For example, ColorTween specifies a progression between two colors.

colorTween = ColorTween(begin: Colors.transparent, end: Colors.black54);

A Tween stores mutable begin and end values, but doesn't track animation progress. Instead, it provides the evaluate(Animation<double> animation) method that uses the transform function to map the current value of the animation (between 0.0 and 1.0) to the actual animation value.

The current value of the Animation object is available from the .value getter. The tween returns begin and end when the animation values are 0.0 and 1.0, respectively.

Tween.animate

To use a Tween object, call animate() on the Tween, passing in the controller object. For example, the following code generates the integer values from 0 to 255 over the course of 500 ms.

final AnimationController controller = AnimationController(
  duration: const Duration(milliseconds: 500),
  vsync: this,
);
final Animation&#x3C;int> alpha = IntTween(
  begin: 0,
  end: 255,
).animate(controller);

not an Animatable.

final AnimationController controller = AnimationController(
  duration: const Duration(milliseconds: 500),
  vsync: this,
);
final Animation&#x3C;double> curve = CurvedAnimation(
  parent: controller,
  curve: Curves.easeOut,
);
final Animation&#x3C;int> alpha = IntTween(begin: 0, end: 255).animate(curve);

Animation notifications

An Animation object can have listeners and status listeners, registered with addListener() and addStatusListener(). A listener is called whenever the value of the animation changes. The most common behavior of a listener is to call setState() to cause a rebuild. A status listener is called when an animation begins, ends, moves forward, or moves in reverse, as defined by AnimationStatus.

Codelabs, tutorials, and articles

The following resources are a good place to start learning the Flutter animation framework. Each of these documents shows how to write animation code.

  • Animations in Flutter codelab Learn about implicit and explicit animations while building a multiple-choice quiz game.

  • Animations tutorial Explains the fundamental classes in the Flutter animation package (controllers, Animatable, curves, listeners, builders), as it guides you through a progression of tween animations using different aspects of the animation APIs. This tutorial shows how to create your own custom explicit animations.

  • Zero to One with Flutter, part 1 and part 2 Flutter blog posts showing how to create an animated chart using tweening.

  • Casual games toolkit A toolkit with game templates that contain examples of how to use Flutter animations.

Other resources

Learn more about Flutter animations at the following links:

Was this useful?

Content from flutter/website, © The Flutter Authors, used under the Creative Commons Attribution 3.0 License; code samples under the BSD License.

Introduction to animations (official source) · Boring Doc