Flutter – Trabajar con animaciones

Siempre que la creación de una aplicación, la animación juega un papel vital en el diseño de la experiencia del usuario. A la gente le suele gustar una aplicación que tiene un flujo suave y un diseño elegante. El paquete Flutter proporciona una variedad de métodos para crear y usar animaciones en nuestra aplicación. Discutiremos los widgets de Flutter incorporados para manejar la animación.

Animación en Flutter

Como muestra el diagrama de flujo para manejar la animación en Flutter, el marco proporciona widgets de diferente capacidad e implementación. La propiedad básica que está presente en todos los widgets de animación es la Duración y la Curva . La Duración es el tiempo durante el cual se anima el widget y la Curva define la forma en que se anima el objeto y de principio a fin (El flujo de la animación de principio a fin). Los widgets de animación incorporados en flutter se pueden dividir en dos categorías principales.

Widgets implícitos

Estos son los widgets más simples proporcionados por flutter. Estos widgets se pueden implementar sin mucho trabajo por parte del desarrollador. Estas son técnicas de animación muy básicas, por lo que no tienen muchas opciones disponibles para cambiar. Tienen animación unidireccional que no es continua. Los widgets implícitos a su vez se pueden clasificar en dos como

  • AnimatedXYZ : aquí XYZ es un widget específico disponible para ser animado. Estas son versiones animadas de los widgets básicos disponibles en Flutter. Estos son algunos de los XYZ animados implícitos de los widgets XYZ existentes.
  1. Alinear → Alinear animado
  2. Contenedor → Contenedor animado
  3. DefaultTextStyle → AnimatedDefaultTextStyle
  4. Relleno → Relleno animado
  5. Posicionado → AnimadoPosicionado
  • TweenAnimationBuilder : estos widgets animan un widget dado desde un valor inicial ( Tween.begin ) hasta un valor final ( Tween.end ). Este widget se puede usar para animar un widget personalizado para una animación simple. Admite una propiedad de constructor que construye la Animación en función del valor proporcionado en su parámetro. También podemos proporcionar lo que debe hacerse cuando la animación se completa con la ayuda de la devolución de llamada onEnd .

Widget explícito

Estos widgets proporcionan un control más granular sobre el widget animado. Tienen las propiedades para controlar la repetición y el movimiento del widget. Estos widgets requieren un AnimationController para el control granular que brindan. Este controlador se puede definir en initState y disponer de estados para un mejor uso. El widget explícito se puede categorizar como

  • XYZTransition : Aquí XYZ es un widget específico disponible como Transición. Estas son transiciones integradas que proporcionan más control sobre la animación implícita. Se pueden considerar como una extensión del widget AnimatedXYZ . Algunas Transiciones XYZ explícitas disponibles son:
  1. SizeTransition
  2. DesvanecimientoTransición
  3. AlinearTransición
  4. RotaciónTransición
  5. Transición posicionada
  6. DecoradoCuadroTransición
  • AnimatedBuilder/ AnimatedWidget : cuando no hay widgets disponibles de XYZTransition predefinidos que ya definen una variedad de animaciones, entonces podemos usar AnimatedBuilder / AnimatedWidget . Se aplican a un widget personalizado que queremos animar explícitamente. Si podemos definir la animación en el mismo widget, entonces podemos usar AnimatedBuilder; de lo contrario, si definimos un widget nuevo, podemos extender el widget definido con el Widget animado.

Ahora que hemos cubierto la definición básica del widget de animación incorporado. Vamos a ver un ejemplo de cada uno de ellos uno por uno.

Vamos a configurar la aplicación. Primero, crearemos el directorio de imágenes en la raíz y agregaremos las dos imágenes como bird.png e hypno.png que se proporcionan a continuación .

hipno.png

pájaro.png

Después de esto, en pubspec.yaml, agregue las siguientes líneas debajo de los activos y haga clic en Pub para usar las imágenes .

assets:
    - images/ #Add

Ahora que se han agregado los recursos, definiremos el contenido del directorio lib. Vamos a crear cuatro nuevos archivos dart como animation_xyz.dart, tween_animation.dart, xyz_transition.dart y builder_animation.dart además de main.dart.

El main.dart tiene el siguiente código

Dart

import 'package:flutter/material.dart';
import 'builder_animation.dart';
import 'xyz_transition.dart';
import 'tween_animation.dart';
import 'animated_xyz.dart';
  
void main() {
  runApp(MyApp());
}
  
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Animation Demo',
      theme: ThemeData(
        primarySwatch: Colors.green,
      ),
      home: Home(),
    );
  }
}
  
class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 4,
      child: Scaffold(
          
        // define appbar here
        appBar: AppBar(
            
          // add tabs to the app
          bottom: TabBar(
            tabs: [
              Tab(text: 'Ani..XYZ'),
              Tab(text: 'Tween'),
              Tab(text: 'XYZTra..'),
              Tab(text: 'Builder'),
            ],
          ),
          title: Text('GeeksforGeeks'),
        ),
        body: TabBarView(
            
          // animations
          children: [
            AnimatedXYZ(),
            TweenAnimation(),
            XYZTransition(),
            BuilderAnimation(),
          ],
        ),
      ),
    );
  }
}

Aquí hemos creado un Scaffold que contiene una barra de aplicaciones y, aparte de esto, la barra de aplicaciones tiene una barra de pestañas que muestra las diferentes pantallas para diferentes tipos de animación.

De forma predeterminada, la pantalla principal muestra el widget AnimatedXYZ que hemos definido en el archivo animation_xyz.dart . Esto muestra el primer tipo de widget implícito del que hemos hablado. El archivo tiene el siguiente código.

Dart

import 'package:flutter/material.dart';
  
class AnimatedXYZ extends StatefulWidget {
  @override
  _AnimatedXYZState createState() => _AnimatedXYZState();
}
  
// building the container class
class _AnimatedXYZState extends State<AnimatedXYZ> {
  bool _toggle = true;
  
  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Padding(
              padding: const EdgeInsets.all(20),
              child: Text(
                'AnimatedContainer',
                style: TextStyle(fontSize: 20),
              ),
            ),
              
            // using the AnimatedContainer widget
            AnimatedContainer(
              decoration: BoxDecoration(
                color: _toggle == true
                    ? Colors.blueAccent
                    : Colors.deepPurpleAccent,
                borderRadius: BorderRadius.all(Radius.circular(8)),
              ),
              curve: Curves.easeInOutBack,
              duration: Duration(seconds: 1),
              height: _toggle == true ? 100 : 400,
              width: _toggle == true ? 100 : 200,
            ),
            SizedBox(
              height: 20,
            ),
            RaisedButton(
              onPressed: () {
                setState(() {
                  _toggle = !_toggle;
                });
              },
              child: Text('Animate'),
            )
          ],
        ),
      ),
    );
  }
}

Este archivo tiene una Columna que contiene diferentes widgets y un AnimatedContainer que aparte de las funciones normales también tiene definida una curva y una duración. Cuando se presiona el botón, el tamaño y el color del Contenedor cambian como se muestra:

En la pantalla siguiente, hemos realizado una animación de interpolación en el archivo tween_animation.dart . En esta animación, tenemos una imagen de un pájaro que al presionar el botón cambia el color del pájaro. El archivo tiene el siguiente código.

Dart

import 'package:flutter/material.dart';
  
class TweenAnimation extends StatefulWidget {
  @override
  _TweenAnimationState createState() => _TweenAnimationState();
}
  
class _TweenAnimationState extends State<TweenAnimation> {
  Color c1 = Colors.white;
  Color c2 = Colors.yellow;
  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(
              'TweenAnimation',
              style: TextStyle(fontSize: 20),
            ),
            SizedBox(
              height: 10,
            ),
              
            // Using TweenAnimationBuilder
            TweenAnimationBuilder(
              tween: ColorTween(begin: c1, end: c2),
              duration: Duration(seconds: 1),
              builder: (_, Color color, __) {
                return ColorFiltered(
                    
                  // image assets
                  child: Image.asset(
                    'images/bird.png',
                    height: 180,
                  ),
                  colorFilter: ColorFilter.mode(color, BlendMode.modulate),
                );
              },
            ),
            SizedBox(
              height: 20,
            ),
              
            // button
            RaisedButton(
              onPressed: () {
                setState(() {
                  c1 = c1 == Colors.white ? Colors.yellow : Colors.white;
                  c2 = c2 == Colors.yellow ? Colors.white : Colors.yellow;
                });
              },
              child: Text('Change Color'),
            )
          ],
        ),
      ),
    );
  }
}

En este archivo, simplemente hemos definido una Columna que contiene los diferentes widgets y además de estos tiene un TweenAnimationBuilder que acepta el tipo de interpolación (aquí hemos usado ColorTween ) y la duración de la animación. También tiene una propiedad de construcción que crea el widget proporcionado de acuerdo con la interpolación.

Ahora que hemos terminado con la animación implícita. Definiremos la animación explícita en las próximas dos pantallas. Los widgets de animación explícitos brindan más control manual sobre cómo administrar nuestras animaciones.

La tercera pantalla muestra un ejemplo de RotationTransition . El código es el siguiente

Dart

import 'package:flutter/material.dart';
  
class XYZTransition extends StatefulWidget {
  @override
  _XYZTransitionState createState() => _XYZTransitionState();
}
  
class _XYZTransitionState extends State<XYZTransition>
    with SingleTickerProviderStateMixin {
  AnimationController _animationController;
  
  @override
  void initState() {
    super.initState();
    _animationController = AnimationController(
      vsync: this,
      duration: Duration(seconds: 3),
    )..repeat();
  }
  
  @override
  void dispose() {
    _animationController.dispose();
    super.dispose();
  }
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(
              'RotationalTransition',
              style: TextStyle(fontSize: 20),
            ),
            SizedBox(
              height: 10,
            ),
              
            // assign action to gestures
            GestureDetector(
              onTap: () {
                _animationController.isAnimating
                    ? _animationController.stop()
                    : _animationController.repeat();
              },
              child: Padding(
                padding: const EdgeInsets.all(8.0),
                child: Center(
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                        
                      // defining the animation type
                      RotationTransition(
                        child: Image.asset('images/hypno.png',
                            height: 150, width: 150),
                        alignment: Alignment.center,
                        turns: _animationController,
                      ),
                      SizedBox(
                        height: 20,
                      ),
                      Text('Tap to STOP/ START')
                    ],
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

Los widgets explícitos nos brindan más control manual. Para tener acceso a estos controles necesitamos tener un controlador. Así que definimos un objeto AnimationController para esto. Necesitamos inicializar la animación cuando se construye la pantalla y también desecharla cuando nos movemos a otra pantalla. Aquí hemos usado RotationTransition para rotar la imagen dada infinitamente. La rotación se puede detener/reiniciar tocando la imagen como se menciona en la pantalla. La transición acepta el objeto AnimationController como los giros. Hemos definido repetir la animación una vez completada en initState .

La animación explícita mencionada anteriormente funciona en la Transición XYZ predefinida, pero para trabajar en nuestro objeto personalizado, podemos usar AnimationBuilder para crear nuestra propia animación. El código es el siguiente

Dart

import 'package:flutter/material.dart';
  
class BuilderAnimation extends StatefulWidget {
  @override
  _BuilderAnimationState createState() => _BuilderAnimationState();
}
  
class _BuilderAnimationState extends State<BuilderAnimation>
    with TickerProviderStateMixin {
  Animation _starAnimation;
  AnimationController _starAnimationController;
  
  bool toggle = false;
  
  // animation controller
  @override
  void initState() {
    super.initState();
    _starAnimationController =
        AnimationController(vsync: this, duration: Duration(milliseconds: 500));
    _starAnimation = Tween(begin: 140.0, end: 160.0).animate(CurvedAnimation(
        curve: Curves.elasticInOut, parent: _starAnimationController));
  
    _starAnimationController.addStatusListener((AnimationStatus status) {
      if (status == AnimationStatus.completed) {
        _starAnimationController.repeat();
      }
    });
  }
  
  @override
  void dispose() {
    super.dispose();
    _starAnimationController?.dispose();
  }
  
  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Text(
            'AnimatedBuilder',
            style: TextStyle(fontSize: 20),
          ),
          SizedBox(
            height: 10,
          ),
            
          // animated container 
          // goes as a child
          Container(
            height: 200,
            width: 200,
            child: AnimatedBuilder(
              animation: _starAnimationController,
              builder: (context, child) {
                return Center(
                  child: Container(
                    child: Center(
                      child: Icon(
                        Icons.audiotrack,
                        color: Colors.orangeAccent,
                        size: _starAnimation.value,
                      ),
                    ),
                  ),
                );
              },
            ),
          ),
          SizedBox(
            height: 10,
          ),
            
          // button
          RaisedButton(
            child: Text('START/ STOP'),
            onPressed: () {
              toggle = !toggle;
              toggle == true
                  ? _starAnimationController.forward()
                  : _starAnimationController.stop();
            },
          ),
        ],
      ),
    );
  }
}

Este widget muestra un ícono de pista de música que crece repetidamente. La mayoría de los detalles siguen siendo los mismos de la Transición XYZ explícita definida anteriormente. Pero aquí tenemos que pasar un constructor con un niño y el contexto. Aquí tenemos que pasar el controlador a la propiedad animation del AnimatedBuilder . El botón se utiliza para iniciar y detener la animación.

La salida de todas las pantallas de animación:

Publicación traducida automáticamente

Artículo escrito por muazzamfaraaz y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *