AnimationController class Null safety

A controller for an animation.

This class lets you perform tasks such as:

By default, an AnimationController linearly produces values that range from 0.0 to 1.0, during a given duration. The animation controller generates a new value whenever the device running your app is ready to display a new frame (typically, this rate is around 60 values per second).

Ticker providers

An AnimationController needs a TickerProvider, which is configured using the vsync argument on the constructor.

The TickerProvider interface describes a factory for Ticker objects. A Ticker is an object that knows how to register itself with the SchedulerBinding and fires a callback every frame. The AnimationController class uses a Ticker to step through the animation that it controls.

If an AnimationController is being created from a State, then the State can use the TickerProviderStateMixin and SingleTickerProviderStateMixin classes to implement the TickerProvider interface. The TickerProviderStateMixin class always works for this purpose; the SingleTickerProviderStateMixin is slightly more efficient in the case of the class only ever needing one Ticker (e.g. if the class creates only a single AnimationController during its entire lifetime).

The widget test framework WidgetTester object can be used as a ticker provider in the context of tests. In other contexts, you will have to either pass a TickerProvider from a higher level (e.g. indirectly from a State that mixes in TickerProviderStateMixin), or create a custom TickerProvider subclass.

Life cycle

An AnimationController should be disposed when it is no longer needed. This reduces the likelihood of leaks. When used with a StatefulWidget, it is common for an AnimationController to be created in the State.initState method and then disposed in the State.dispose method.

Using Futures with AnimationController

The methods that start animations return a TickerFuture object which completes when the animation completes successfully, and never throws an error; if the animation is canceled, the future never completes. This object also has a TickerFuture.orCancel property which returns a future that completes when the animation completes successfully, and completes with an error when the animation is aborted.

This can be used to write code such as the fadeOutAndUpdateState method below.

Here is a stateful Foo widget. Its State uses the SingleTickerProviderStateMixin to implement the necessary TickerProvider, creating its controller in the State.initState method and disposing of it in the State.dispose method. The duration of the controller is configured from a property in the Foo widget; as that changes, the State.didUpdateWidget method is used to update the controller.
class Foo extends StatefulWidget {
  const Foo({ super.key, required this.duration });

  final Duration duration;

  @override
  State<Foo> createState() => _FooState();
}

class _FooState extends State<Foo> with SingleTickerProviderStateMixin {
  late AnimationController _controller;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      vsync: this, // the SingleTickerProviderStateMixin
      duration: widget.duration,
    );
  }

  @override
  void didUpdateWidget(Foo oldWidget) {
    super.didUpdateWidget(oldWidget);
    _controller.duration = widget.duration;
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Container(); // ...
  }
}

The following method (for a State subclass) drives two animation controllers using Dart's asynchronous syntax for awaiting Future objects:
Future<void> fadeOutAndUpdateState() async {
  try {
    await fadeAnimationController.forward().orCancel;
    await sizeAnimationController.forward().orCancel;
    setState(() {
      dismissed = true;
    });
  } on TickerCanceled {
    // the animation got canceled, probably because we were disposed
  }
}

The assumption in the code above is that the animation controllers are being disposed in the State subclass' override of the State.dispose method. Since disposing the controller cancels the animation (raising a TickerCanceled exception), the code here can skip verifying whether State.mounted is still true at each step. (Again, this assumes that the controllers are created in State.initState and disposed in State.dispose, as described in the previous section.)

See also:

Inheritance
Mixed in types

Constructors

AnimationController({double? value, Duration? duration, Duration? reverseDuration, String? debugLabel, double lowerBound = 0.0, double upperBound = 1.0, AnimationBehavior animationBehavior = AnimationBehavior.normal, required TickerProvider vsync})
Creates an animation controller.
AnimationController.unbounded({double value = 0.0, Duration? duration, Duration? reverseDuration, String? debugLabel, required TickerProvider vsync, AnimationBehavior animationBehavior = AnimationBehavior.preserve})
Creates an animation controller with no upper or lower bound for its value.

Properties

animationBehavior AnimationBehavior
The behavior of the controller when AccessibilityFeatures.disableAnimations is true.
final
debugLabel String?
A label that is used in the toString output. Intended to aid with identifying animation controller instances in debug output.
final
duration Duration?
The length of time this animation should last.
read / write
hashCode int
The hash code for this object.
read-onlyinherited
isAnimating bool
Whether this animation is currently animating in either the forward or reverse direction.
read-only
isCompleted bool
Whether this animation is stopped at the end.
read-onlyinherited
isDismissed bool
Whether this animation is stopped at the beginning.
read-onlyinherited
lastElapsedDuration Duration?
The amount of time that has passed between the time the animation started and the most recent tick of the animation.
read-only
lowerBound double
The value at which this animation is deemed to be dismissed.
final
reverseDuration Duration?
The length of time this animation should last when going in reverse.
read / write
runtimeType Type
A representation of the runtime type of the object.
read-onlyinherited
status AnimationStatus
The current status of this animation.
read-onlyoverride
upperBound double
The value at which this animation is deemed to be completed.
final
value double
The current value of the animation.
read / writeoverride-getter
velocity double
The rate of change of value per second.
read-only
view Animation<double>
Returns an Animation<double> for this animation controller, so that a pointer to this object can be passed around without allowing users of that pointer to mutate the AnimationController state.
read-only

Methods

addListener(VoidCallback listener) → void
Calls the listener every time the value of the animation changes.
inherited
addStatusListener(AnimationStatusListener listener) → void
Calls listener every time the status of the animation changes.
inherited
animateBack(double target, {Duration? duration, Curve curve = Curves.linear}) TickerFuture
Drives the animation from its current value to target.
animateTo(double target, {Duration? duration, Curve curve = Curves.linear}) TickerFuture
Drives the animation from its current value to target.
animateWith(Simulation simulation) TickerFuture
Drives the animation according to the given simulation.
clearListeners() → void
Removes all listeners added with addListener.
protected">@protectedinherited
clearStatusListeners() → void
Removes all listeners added with addStatusListener.
protected">@protectedinherited
didRegisterListener() → void
This implementation ignores listener registrations.
protected">@protectedinherited
didUnregisterListener() → void
This implementation ignores listener registrations.
protected">@protectedinherited
dispose() → void
Release the resources used by this object. The object is no longer usable after this method is called.
override
drive<U>(Animatable<U> child) Animation<U>
Chains a Tween (or CurveTween) to this Animation.
optionalTypeArgs">@optionalTypeArgsinherited
fling({double velocity = 1.0, SpringDescription? springDescription, AnimationBehavior? animationBehavior}) TickerFuture
Drives the animation with a spring (within lowerBound and upperBound) and initial velocity.
forward({double? from}) TickerFuture
Starts running this animation forwards (towards the end).
noSuchMethod(Invocation invocation) → dynamic
Invoked when a non-existent method or property is accessed.
inherited
notifyListeners() → void
Calls all the listeners.
protected">@protectedinherited
notifyStatusListeners(AnimationStatus status) → void
Calls all the status listeners.
protected">@protectedinherited
removeListener(VoidCallback listener) → void
Stop calling the listener every time the value of the animation changes.
inherited
removeStatusListener(AnimationStatusListener listener) → void
Stops calling the listener every time the status of the animation changes.
inherited
repeat({double? min, double? max, bool reverse = false, Duration? period}) TickerFuture
Starts running this animation in the forward direction, and restarts the animation when it completes.
reset() → void
Sets the controller's value to lowerBound, stopping the animation (if in progress), and resetting to its beginning point, or dismissed state.
resync(TickerProvider vsync) → void
Recreates the Ticker with the new TickerProvider.
reverse({double? from}) TickerFuture
Starts running this animation in reverse (towards the beginning).
stop({bool canceled = true}) → void
Stops running this animation.
toString() String
A string representation of this object.
inherited
toStringDetails() String
Provides a string describing the status of this object, but not including information about the object itself.
override

Operators

operator ==(Object other) bool
The equality operator.
inherited