Widgets animados implícitamente en Flutter

Simplificando las animaciones en Flutter con Widgets animados implícitamente

Deven Joshi
Deven Joshi

Sigue

12 de octubre, 2018 – 5 min read

Las animaciones son bastante fáciles de hacer en Flutter y se puede conseguir mucha complejidad con mucho menos esfuerzo que en Android nativo. Esto se logra generalmente a través de formas como la definición de una Animación + un AnimationController. Pero hay widgets incorporados que incluso reducen esto y hacen que las animaciones sean tan fáciles como simplemente cambiar valores!

Los ejemplos completos estarán alojados en mi página de Github dada al final de este artículo.

Un AnimatedContainer en Flutter

Un AnimatedContainer transiciona automáticamente a los valores definidos (colores, tamaños, etc.) en lugar de cambiar instantáneamente a ellos. El GIF de arriba es un ejemplo de un AnimatedContainer.

Un AnimatedContainer se define como:

var myColor = Colors.blue;
var myHeight = 100.0;
var myWidth = 100.0;AnimatedContainer(
duration: Duration(seconds: 1),
color: myColor,
height: myHeight,
width: myWidth,
),

En casos normales, definirías un controlador y una Tween<double> y una ColorTween para conseguir la animación del GIF de arriba. Pero con AnimatedContainer, todo lo que tienes que hacer es:

  1. Establecer una duración para la animación
 duration: Duration(seconds: 1),

2. Cambiar los valores (Cambiar el color y el tamaño a sus valores)

 myColor = Colors.green;
myHeight = MediaQuery.of(context).size.height;
myWidth = MediaQuery.of(context).size.width;

3. SetState()

 setState(() {});

Sin controladores. Sin Tweens.

En el momento en que cambias los valores de miColor, miAltura o miAncho y setState(), el contenedor transita automáticamente a los valores en lugar de cambiar directamente a ese valor.

onPressed: () {
myColor = Colors.green;
myHeight = MediaQuery.of(context).size.height;
myWidth = MediaQuery.of(context).size.width;
setState(() {});
}

Al principio, miColor estaba establecido en Colors.blue. Cuando lo cambiamos a Colors.green y setState para reconstruirlo, hace la transición de azul a verde sin utilizar ningún Tweens. (Nota: Los Tweens se usan implícitamente pero no necesitan ser definidos por el usuario.)

Por lo que he visto, muchos desarrolladores no parecen ser conscientes de estos widgets animados implícitamente y pierden el tiempo cuando no es necesario. Obviamente habrá casos en los que se quiera un comportamiento diferente, pero la mayoría de las veces, AnimatedContainer hace el trabajo.

Animaciones de Héroes

Animaciones de Héroes en Flutter

Una animación de Héroes hace que un elemento de una página «vuele» a la segunda y se ajuste automáticamente al tamaño del mismo elemento en la segunda página. Esto hace que algo como una lista en una aplicación que tiene una página de detalles sea mucho más interesante.

Flutter hace que sea increíblemente fácil implementar animaciones Hero. Todo lo que tienes que hacer es envolver el elemento que quieres hacer un ‘Héroe’ con un widget de Héroe y suministrarle una etiqueta. Si quieres hacer esto en una lista, tienes que suministrar una etiqueta diferente para cada elemento, que yo sólo suelo establecer como «héroe» + posición del elemento en la lista.

El ejemplo anterior tiene una simple tarjeta en la primera página con un contenedor con un color rojo.

Hero(
tag: "heroTag",
child: Container(
color: Colors.red,
height: 100.0,
),
),

En la página de detalle, de nuevo hay un contenedor más grande con un color rojo también.

Expanded(
child: Hero(
tag: "heroTag",
child: Container(
color: Colors.red,
),
),
),

Y una vez que lo empujo de una página a la otra usando

Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return new HeroDetailPage();
},
),
);

¡Eso es!

El contenedor de color vuela automáticamente y se expande al tamaño de este último.

Hace un tiempo, utilicé un montón de animaciones en una app de ajedrez conceptual que creé con Flutter.

Aquí tienes un artículo que escribí si quieres ver con más detalle el código de esta app.

AnimatedCrossFade

AnimatedCrossFades in Flutter

Un CrossFade es una transición suave de un widget a otro con una duración determinada. Flutter lo hace fácil utilizando un widget AnimatedCrossFade.

Así se define un AnimatedCrossFade:

AnimatedCrossFade(
firstChild: // Your first element here,
secondChild: // Element after transition,
crossFadeState: // State of the transition,
duration: Duration(milliseconds: 1500),
),

Suministramos:

  1. El widget antes de la transición
firstChild: Container(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: CircularProgressIndicator(),
),
height: 200.0,
width: 200.0,
),

2. El widget después de la transición

secondChild: Container(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: FlutterLogo(),
),
height: 100.0,
width: 200.0,
),

3. El estado de la transición (Si la transición ha ocurrido ya o no)

(Aquí, firstStateEnabled es un booleano que podemos cambiar para cambiar el estado.)

crossFadeState: firstStateEnabled
? CrossFadeState.showFirst
: CrossFadeState.showSecond,

4. La duración de la transición

duration: Duration(milliseconds: 1500),

Esta cantidad de código es suficiente para darnos el ejemplo anterior. La transición se dispara simplemente cambiando el crossFadeState.

Nota: Si los dos hijos son de diferente tamaño entonces se transiciona automáticamente de un tamaño a otro.

Aquí tienes una demostración:

AnimatedOpacity

AnimatedOpacity anima los cambios de opacidad, es decir.es decir, lo visible que es un widget. Una opacidad de 0 hace que un widget sea completamente transparente, mientras que una opacidad de 1 es totalmente visible.

AnimatedOpacity se declara como:

AnimatedOpacity(
opacity: // Your variable holding opacity value,
duration: // Duration of the transition,
child: FlutterLogo(),
)

Siguiendo con los últimos widgets, en AnimatedOpacity, cambias la opacidad y setState y automáticamente anima el cambio de opacidad.

En el ejemplo anterior, se declara como

AnimatedOpacity(
child: FlutterLogo(size: 100.0,),
opacity: myOpacity,
duration: Duration(seconds: 1),
),

Cuando se hace clic en el botón, simplemente cambia la opacidad y establece el estado.

onPressed: () {
myOpacity = 0.0;
setState(() {});
},

Deja un comentario