Resumen de la API de animaciones
Un resumen de los conceptos de animación.
El sistema de animación en Flutter se basa en objetos tipados
Animation.
Los widgets pueden incorporar estas animaciones directamente
en sus funciones build leyendo su valor actual y escuchando sus
cambios de estado o pueden usar las animaciones como base para animaciones
más elaboradas que pasan a otros widgets.
Animación
#El bloque de construcción principal del sistema de animación es la
clase Animation.
Una animación representa un valor
de un tipo específico que puede cambiar a lo largo de la vida útil de
la animación. La mayoría de los widgets que realizan una animación
reciben un objeto Animation como parámetro,
del cual leen el valor actual de la animación
y al cual escuchan para detectar cambios en ese valor.
addListener
#
Cada vez que cambia el valor de la animación,
la animación notifica a todos los listeners agregados con
addListener. Típicamente, un objeto
State
que escucha una animación llama a
setState
sobre sí mismo en su callback de listener
para notificar al sistema de widgets que necesita
reconstruirse con el nuevo valor de la animación.
Este patrón es tan común que existen dos widgets
que ayudan a los widgets a reconstruirse cuando las animaciones cambian de valor:
AnimatedWidget
y AnimatedBuilder.
El primero, AnimatedWidget, es más útil para
widgets animados stateless. Para usar AnimatedWidget,
simplemente crea una subclase de este e implementa la función build.
El segundo, AnimatedBuilder, es útil para widgets más complejos
que desean incluir una animación como parte de una función build más grande.
Para usar AnimatedBuilder, simplemente construye el widget
y pásale una función builder.
addStatusListener
#
Las animaciones también proporcionan un AnimationStatus,
que indica cómo evolucionará la animación con el tiempo.
Cada vez que cambia el estado de la animación,
la animación notifica a todos los listeners agregados con
addStatusListener. Típicamente, las animaciones comienzan
en el estado dismissed, lo que significa que están
al principio de su rango. Por ejemplo,
las animaciones que avanzan de 0.0 a 1.0
estarán dismissed cuando su valor sea 0.0.
Una animación podría ejecutarse hacia adelante (forward, de 0.0 a 1.0)
o tal vez en reversa (reverse, de 1.0 a 0.0).
Eventualmente, si la animación alcanza el final de su rango
(1.0), la animación alcanza el estado completed.
AnimationController
#Para crear una animación, primero crea un AnimationController.
Además de ser una animación en sí misma, un AnimationController
te permite controlar la animación. Por ejemplo,
puedes decirle al controlador que ejecute la animación
forward
o que detenga (stop)
la animación.
También puedes lanzar (fling)
animaciones,
lo que utiliza una simulación física, como un resorte,
para impulsar la animación.
Una vez que hayas creado un controlador de animación,
puedes comenzar a construir otras animaciones basadas en él.
Por ejemplo, puedes crear un ReverseAnimation
que refleje la animación original pero se ejecute en la
dirección opuesta (de 1.0 a 0.0).
De manera similar, puedes crear un CurvedAnimation
cuyo valor se ajusta mediante una Curve.
Tweens
#Para animar más allá del intervalo de 0.0 a 1.0, puedes usar un
Tween<T>, que interpola entre sus
valores begin
y end. Muchos tipos tienen subclases
específicas de Tween que proporcionan interpolación específica de tipo.
Por ejemplo, ColorTween
interpola entre colores y
RectTween
interpola entre rectángulos (rects).
Puedes definir tus propias interpolaciones creando
tu propia subclase de Tween y sobrescribiendo su
función lerp.
Por sí solo, un tween simplemente define cómo interpolar entre dos valores. Para obtener un valor concreto para el fotograma (frame) actual de una animación, también necesitas una animación para determinar el estado actual. Hay dos formas de combinar un tween con una animación para obtener un valor concreto:
-
Puedes evaluar (
evaluate) el tween en el valor actual de una animación. Este enfoque es muy útil para widgets que ya están escuchando la animación y, por lo tanto, se reconstruyen cada vez que la animación cambia de valor. -
Puedes animar (
animate) el tween basándote en la animación. En lugar de devolver un solo valor, la función animate devuelve una nuevaAnimationque incorpora el tween. Este enfoque es muy útil cuando deseas entregar la animación recién creada a otro widget, el cual puede leer el valor actual que incorpora el tween así como escuchar los cambios en dicho valor.
Arquitectura
#Las animaciones en realidad están construidas a partir de varios bloques de construcción fundamentales.
Scheduler
#El SchedulerBinding
es una clase singleton
que expone las primitivas de programación (scheduling) de Flutter.
Para esta discusión, la primitiva clave son las callbacks de fotograma (frame callbacks).
Cada vez que un fotograma necesita ser mostrado en la pantalla,
el motor de Flutter activa una callback "begin frame" que
el scheduler multiplexa a todos los listeners registrados usando
scheduleFrameCallback(). A todas estas callbacks se les
da la marca de tiempo oficial del fotograma, en
forma de un Duration desde alguna época arbitraria. Dado que todas las
callbacks tienen el mismo tiempo, cualquier animación activada desde estas
callbacks parecerá estar exactamente sincronizada incluso
si tardan unos pocos milisegundos en ejecutarse.
Tickers
#La clase Ticker se engancha al mecanismo
scheduleFrameCallback()
del scheduler para invocar una callback en cada tick.
Un Ticker se puede iniciar y detener. Cuando se inicia,
devuelve un Future que se resolverá cuando se detenga.
En cada tick, el Ticker proporciona a la callback la
duración transcurrida desde el primer tick después de que se inició.
Dado que los tickers siempre entregan su tiempo transcurrido en relación con el primer tick después de que se iniciaron; los tickers están todos sincronizados. Si inicias tres tickers en momentos diferentes entre dos ticks, todos ellos estarán no obstante sincronizados con la misma hora de inicio, y posteriormente marcarán al unísono. Como las personas en una parada de autobús, todos los tickers esperan a un evento que ocurre regularmente (el tick) para comenzar a moverse (contar el tiempo).
Simulations
#La clase abstracta Simulation
mapea un
valor de tiempo relativo (un tiempo transcurrido) a un
valor double, y tiene la noción de finalización.
En principio las simulaciones son stateless, pero en la práctica
algunas simulaciones (por ejemplo,
BouncingScrollSimulation
y
ClampingScrollSimulation)
cambian de estado de forma irreversible cuando se les consulta.
Existen varias implementaciones concretas
de la clase Simulation para diferentes efectos.
Animatables
#La clase abstracta Animatable
mapea un
double a un valor de un tipo determinado.
Las clases Animatable son stateless e inmutables.
Tweens
#La clase abstracta Tween<T>
mapea un valor double
nominalmente en el rango 0.0-1.0 a un valor tipado
(por ejemplo, un Color, u otro double).
Es un Animatable.
Tiene la noción de un tipo de salida (T),
un valor begin y un valor end de ese tipo,
y una forma de interpolar (lerp) entre los valores begin
y end para un valor de entrada dado (el double nominalmente en
el rango 0.0-1.0).
Las clases Tween son stateless e inmutables.
Composición de animatables
#Pasar un Animatable<double> (el padre) al método
chain() de un Animatable crea una nueva subclase de Animatable que aplica el
mapeo del padre y luego el mapeo del hijo.
Curves
#La clase abstracta Curve mapea doubles
nominalmente en el rango 0.0-1.0 a doubles
nominalmente en el rango 0.0-1.0.
Las clases Curve son stateless e inmutables.
Animaciones
#La clase abstracta Animation
proporciona un
valor de un tipo dado, un concepto de dirección
de animación y estado de animación, y una interfaz de listener para
registrar callbacks que se invocan cuando cambia el valor o el estado.
Algunas subclases de Animation tienen valores que nunca cambian
(kAlwaysCompleteAnimation,
kAlwaysDismissedAnimation,
AlwaysStoppedAnimation); registrar callbacks en
estas no tiene ningún efecto ya que los callbacks nunca son llamados.
La variante Animation<double> es especial porque se puede utilizar para
representar un double nominalmente en el rango 0.0-1.0, que es la entrada
esperada por las clases Curve y Tween, así como por algunas subclases más
de Animation.
Algunas subclases de Animation son stateless,
simplemente retransmitiendo listeners a sus padres.
Algunas son muy stateful.
Animaciones componibles
#La mayoría de las subclases de Animation toman un "padre" explícito
Animation<double>. Son impulsadas por ese padre.
La subclase CurvedAnimation toma una clase Animation<double> (el
padre) y un par de clases Curve (las curvas forward y reverse)
como entrada, y usa el valor del padre como entrada para las
curvas para determinar su salida. CurvedAnimation es inmutable y
stateless.
La subclase ReverseAnimation toma una
clase Animation<double> como su padre y revierte
todos los valores de la animación. Asume que el padre
está usando un valor nominalmente en el rango 0.0-1.0 y devuelve
un valor en el rango 1.0-0.0. El estado y la dirección de la animación
padre también se revierten. ReverseAnimation es inmutable y
stateless.
La subclase ProxyAnimation toma una clase Animation<double> como
su padre y simplemente retransmite el estado actual de ese padre.
Sin embargo, el padre es mutable.
La subclase TrainHoppingAnimation toma dos padres,
y alterna entre ellos cuando sus valores se cruzan.
Controladores de animación
#El AnimationController
es un Animation<double> stateful
que utiliza un Ticker para darse vida.
Se puede iniciar y detener. En cada tick, toma el tiempo
transcurrido desde que se inició y lo pasa a una Simulation para obtener
un valor. Ese es entonces el valor que reporta. Si la Simulation
reporta que en ese momento ha terminado, entonces el controlador se detiene
a sí mismo.
Al controlador de animación se le puede dar un límite inferior y superior para animar entre ellos, y una duración.
En el caso simple (usando forward() o reverse()), el controlador de animación simplemente realiza una
interpolación lineal desde el límite inferior al límite superior (o viceversa,
para la dirección inversa) durante la duración dada.
Al usar repeat(), el controlador de animación utiliza una
interpolación lineal entre los límites dados durante la duración dada, pero
no se detiene.
Al usar animateTo(), el controlador de animación realiza una
interpolación lineal durante la duración dada desde el valor actual hasta el
objetivo dado. Si no se proporciona una duración al método, la duración
por defecto del controlador y el rango descrito por los límites inferior y
superior del controlador se utilizan para determinar la velocidad de la
animación.
Al usar fling(), se utiliza un Force para crear una simulación
específica que luego se utiliza para impulsar el controlador.
Al usar animateWith(), la simulación dada se utiliza para impulsar el
controlador.
Todos estos métodos devuelven el future que proporciona el Ticker y
que se resolverá la próxima vez que el controlador se detenga o cambie de
simulación.
Adjuntar animatables a animaciones
#Pasar un Animation<double> (el nuevo padre) al método
animate() de un Animatable crea una nueva subclase de Animation que actúa como
el Animatable pero es impulsada desde el padre dado.
A menos que se indique lo contrario, la documentación de este sitio refleja Flutter 3.44.0. Página actualizada por última vez el 2026-05-05. Ver código fuente oreportar un problema.