Saltar al contenido principal

Animaciones simples

Aprende la forma más sencilla de implementar animaciones en Flutter.

Flutter proporciona un conjunto rico de APIs de animación, y la forma más sencilla de empezar a usarlas es con animaciones implícitas. Las "animaciones implícitas" se refieren a un grupo de Widgets que animan automáticamente los cambios en sus propiedades sin que necesites gestionar ningún comportamiento intermedio.

Qué lograrás

Descubre las animaciones implícitas en Flutter
Animar cambios de propiedades con AnimatedContainer
Personalizar el tiempo con duration y curves

En esta lección, aprenderás sobre uno de los Widgets de animación implícita más comunes y versátiles: AnimatedContainer. Con solo dos líneas de código adicionales, el color de fondo de cada Tile se anima a un nuevo color en aproximadamente medio segundo.


Pasos

1

Convertir Container a AnimatedContainer

Actualmente, el método Tile.build devuelve un Container para mostrar una letra. Cuando hitType cambia, por ejemplo de HitType.none a HitType.hit, el color de fondo del tile cambia instantáneamente. Por ejemplo, de blanco a verde en el caso de HitType.none a HitType.hit.

Como referencia, aquí está la implementación actual del Widget Tile:

dart
class Tile extends StatelessWidget {
  const Tile(this.letter, this.hitType, {super.key});

  final String letter;
  final HitType hitType;

  @override
  Widget build(BuildContext context) {
    return Container(
      height: 60,
      width: 60,
      decoration: BoxDecoration(
        border: Border.all(color: Colors.grey.shade300),
        color: switch (type) {
          HitType.hit => Colors.green,
          HitType.partial => Colors.yellow,
          HitType.miss => Colors.grey,
          _ => Colors.white,
        },
      ),
      child: Center(
        child: Text(
          letter.toUpperCase(),
          style: Theme.of(context).textTheme.titleLarge,
        ),
      ),
    );
  }
}

Para hacer que el cambio de color se anime suavemente, reemplaza el Widget Container por un AnimatedContainer.

Un AnimatedContainer es como un Container, pero anima automáticamente los cambios en sus propiedades durante una duración especificada. Cuando cambian propiedades como color, height, width, decoration o alignment, AnimatedContainer interpola entre los valores antiguos y nuevos, creando una transición suave.

Modifica tu Widget Tile de la siguiente manera:

dart
class Tile extends StatelessWidget {
  const Tile(this.letter, this.hitType, {super.key});

  final String letter;
  final HitType hitType;

  @override
  Widget build(BuildContext context) {
    return AnimatedContainer(
      duration: Duration(milliseconds: 500),
      height: 60,
      width: 60,
      decoration: BoxDecoration(
        border: Border.all(color: Colors.grey.shade300),
        color: switch (hitType) {
          HitType.hit => Colors.green,
          HitType.partial => Colors.yellow,
          HitType.miss => Colors.grey,
          _ => Colors.white,
        },
      ),
      child: Center(
        child: Text(
          letter.toUpperCase(),
          style: Theme.of(context).textTheme.titleLarge,
        ),
      ),
    );
  }
}

duration es una propiedad requerida que especifica cuánto tiempo debe tomar la animación. En este ejemplo, pasar Duration(milliseconds: 500) significa que la transición de color tomará medio segundo. Puedes también especificar segundos, minutos y muchas otras unidades de tiempo.

Ahora, cuando hitType cambia y el Widget Tile se reconstruye (porque se llamó a setState en GamePage), el color del tile se anima suavemente desde su color anterior al nuevo durante la duración especificada.

2

Ajustar la curva de animación

Para añadir un poco de personalización a una animación implícita, puedes pasarle una Curve diferente. Las diferentes curvas cambian la velocidad de la animación en diferentes puntos a lo largo de la animación.

Por ejemplo, la curva por defecto para las animaciones de Flutter es Curves.linear. Este gif muestra cómo se comporta la curva de animación:

Un gif que muestra una curva lineal.

Compara eso con Curve.bounceIn, otra curva común:

Un gif que muestra una curva bounce-in.

Para cambiar la Curve de esta animación, actualiza el código a lo siguiente:

dart
class Tile extends StatelessWidget {
  const Tile(this.letter, this.hitType, {super.key});

  final String letter;
  final HitType hitType;

  @override
  Widget build(BuildContext context) {
    return AnimatedContainer(
      duration: Duration(milliseconds: 500),
      curve: Curves.bounceIn, // NEW
      height: 60,
      width: 60,
      decoration: BoxDecoration(
        border: Border.all(color: Colors.grey.shade300),
        color: switch (hitType) {
          HitType.hit => Colors.green,
          HitType.partial => Colors.yellow,
          HitType.miss => Colors.grey,
          _ => Colors.white,
        },
      ),
      child: Center(
        child: Text(
          letter.toUpperCase(),
          style: Theme.of(context).textTheme.titleLarge,
        ),
      ),
    );
  }
}

El SDK de Flutter proporciona muchas curvas diferentes, así que siéntete libre de probarlas pasando diferentes tipos al parámetro curve.

Las animaciones implícitas como AnimatedContainer son potentes porque solo le dices al Widget cuál debería ser el nuevo estado, y este se encarga del "cómo" de la animación.

Para animaciones complejas y personalizadas, puedes escribir tus propios Widgets animados. Si tienes curiosidad, pruébalo en el tutorial de animaciones.

3

Revisión

Qué lograste

Aquí tienes un resumen de lo que construiste y aprendiste en esta lección.
Descubrí las animaciones implícitas

Las animaciones implícitas son Widgets que animan automáticamente los cambios en sus propiedades. Tú especificas el nuevo estado, y el Widget maneja la animación por ti sin requerir una gestión manual de la animación.

Animé los tiles con AnimatedContainer

Al reemplazar Container con AnimatedContainer y añadir una duration, tus tiles ahora realizan la transición entre colores de forma suave. ¡Con solo dos líneas de código, añadiste un pulido profesional a tu app!

Personalicé el tiempo con duration y curves

La propiedad duration controla cuánto tiempo toma la animación, mientras que curve cambia la sensación de la animación. Probaste Curves.decelerate, pero también puedes probar otros valores como Curves.easeIn, Curves.bounceOut o Curves.elasticIn.

Completé el juego Birdle

¡Has construido un juego completo al estilo Wordle con Widgets personalizados, diseños dinámicos, entrada de usuario, administración del State y animaciones fluidas. ¡Ahora tienes las habilidades fundamentales para construir tus propias aplicaciones Flutter!

4

Ponte a prueba

Quiz de animaciones implícitas

1 / 2
What widget can you use to automatically animate changes to properties like color, size, and decoration?
  1. Container

    No exactamente.

    Container no se anima; los cambios de propiedades ocurren instantáneamente.

  2. TransitionContainer

    No exactamente.

    No existe el Widget TransitionContainer; usa AnimatedContainer para animaciones implícitas.

  3. AnimatedContainer

    ¡Así es!

    AnimatedContainer anima automáticamente los cambios en sus propiedades durante la duración especificada.

  4. AnimationController

    No exactamente.

    AnimationController es para animaciones explícitas; AnimatedContainer es más simple para animaciones básicas.

What does the duration property control in an AnimatedContainer?
  1. El retraso antes de que comience la animación.

    No exactamente.

    La duración se refiere a la longitud de la animación; los retrasos requieren una configuración separada.

  2. Cuánto tiempo permanece el Widget en pantalla antes de desaparecer.

    No exactamente.

    La duración controla el tiempo de animación, no la visibilidad del Widget.

  3. Cuánto tiempo tarda la animación en hacer la transición del valor antiguo al nuevo valor.

    ¡Así es!

    La duración especifica el tiempo durante el cual se anima el cambio de propiedad.

  4. Cuántas veces se repite la animación.

    No exactamente.

    Las animaciones implícitas se ejecutan una vez por cambio de estado; la repetición requiere controladores de animación explícitos.