Explorando las animaciones de Flutter: de lo simple a lo complejo

Mar 03 2023
Flutter ofrece una amplia gama de herramientas para crear animaciones sorprendentes en su aplicación. Desde simples fundidos de entrada hasta animaciones complejas basadas en la física, existen infinitas posibilidades para agregar estilo visual a su interfaz de usuario.

Flutter ofrece una amplia gama de herramientas para crear animaciones sorprendentes en su aplicación. Desde simples fundidos de entrada hasta animaciones complejas basadas en la física, existen infinitas posibilidades para agregar estilo visual a su interfaz de usuario. En este artículo, exploraremos algunos de los conceptos básicos de la animación en Flutter y avanzaremos hacia ejemplos más complejos.

  1. Primeros pasos con AnimationController La AnimationControllerclase está en el corazón de todas las animaciones de Flutter. Proporciona una forma de crear animaciones que se pueden controlar y manipular con el tiempo. Este es un ejemplo del uso de an AnimationControllerpara crear una animación de fundido de entrada simple:
  2. class FadeInAnimation extends StatefulWidget {
      final Widget child;
      final Duration duration;
    
      FadeInAnimation({required this.child, this.duration = const Duration(milliseconds: 500)});
    
      @override
      _FadeInAnimationState createState() => _FadeInAnimationState();
    }
    
    class _FadeInAnimationState extends State<FadeInAnimation> with SingleTickerProviderStateMixin {
      late AnimationController _controller;
      late Animation<double> _opacityAnimation;
    
      @override
      void initState() {
        super.initState();
        _controller = AnimationController(vsync: this, duration: widget.duration);
        _opacityAnimation = Tween<double>(begin: 0, end: 1).animate(_controller);
        _controller.forward();
      }
    
      @override
      void dispose() {
        _controller.dispose();
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return AnimatedBuilder(
          animation: _opacityAnimation,
          builder: (BuildContext context, Widget? child) {
            return Opacity(
              opacity: _opacityAnimation.value,
              child: widget.child,
            );
          },
        );
      }
    }
    

class ColorAnimation extends AnimatedWidget {
  final Widget child;

  ColorAnimation({required Animation<Color?> animation, required this.child})
      : super(listenable: animation);

  @override
  Widget build(BuildContext context) {
    final Animation<Color?> animation = listenable as Animation<Color?>;
    return ColorFiltered(
      colorFilter: ColorFilter.mode(animation.value!, BlendMode.modulate),
      child: child,
    );
  }
}

class ColorAnimationExample extends StatefulWidget {
  @override
  _ColorAnimationExampleState createState() => _ColorAnimationExampleState();
}

class _ColorAnimationExampleState extends State<ColorAnimationExample>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<Color?> _colorAnimation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(vsync: this, duration: Duration(seconds: 2));
    _colorAnimation =
        ColorTween(begin: Colors.red, end: Colors.blue).animate(_controller);
    _controller.repeat(reverse: true);
  }

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

  @override
  Widget build(BuildContext context) {
    return Center(
      child: ColorAnimation(
        animation: _colorAnimation,
        child: Container(
          width: 200,
          height: 200,
          decoration: BoxDecoration(
            shape: BoxShape.circle),
      child: Center(
        child: Text(
          "Hello, World!",
          style: TextStyle(fontSize: 24),
        ),
      ),
    ),
  ),
);
}
}

3. Trabajar con curvas y animaciones
Las animaciones en Flutter se pueden personalizar con curvas, que definen cómo progresa la animación con el tiempo. Hay varias curvas integradas disponibles, como `Curves.linear` y `Curves.easeInOut`. Aquí hay un ejemplo del uso de una curva personalizada para crear una animación hinchable:

class BouncyAnimation extends StatefulWidget {
final Widget child;
final Duration duration;

BouncyAnimation({required this.child, this.duration = const Duration(milliseconds: 500)});

@override
_BouncyAnimationState createState() => _BouncyAnimationState();
}

class _BouncyAnimationState extends State<BouncyAnimation>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _animation;

@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this, duration: widget.duration, lowerBound: -0.5, upperBound: 1.0);
_animation = Tween<double>(begin: 0, end: 1).animate(
CurvedAnimation(
parent: _controller,
curve: Curves.bounceOut,
),
);
_controller.forward();
}

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

@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _animation,
builder: (BuildContext context, Widget? child) {
return Transform.scale(
scale: 1 + _animation.value,
child: widget.child,
);
},
);
}
}

4. Animación de widgets complejos con CustomPaint
A veces, los widgets incorporados no son suficientes para crear la animación que desea. En esos casos, puede usar el widget `CustomPaint` para crear sus propias animaciones personalizadas. Aquí hay un ejemplo del uso de `CustomPaint` para crear una animación de degradado giratorio:

class GradientAnimation extends StatefulWidget {
final Widget child;
final Duration duration;

GradientAnimation({required this.child, this.duration = const Duration(seconds: 2)});

@override
_GradientAnimationState createState() => _GradientAnimationState();
}

class _GradientAnimationState extends State<GradientAnimation>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _animation;

@override
void initState() {
super.initState();
_controller = AnimationController(vsync: this, duration: widget.duration)
..repeat();
_animation = Tween<double>(begin: 0, end: 2 * math.pi).animate(_controller);
}

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

@override
Widget build(BuildContext context) {
return CustomPaint(
painter: GradientPainter(_animation),
child: widget.child,
);
}
}
class GradientPainter extends CustomPainter {
final Animation<double> animation;

GradientPainter(this.animation) : super(repaint: animation);

@override
void paint(Canvas canvas, Size size) {
final rect = Offset.zero & size;
final gradient = SweepGradient(
center: Alignment.center,
colors: [
Colors.red,
Colors.green,
Colors.blue,
],
startAngle: animation.value,
endAngle: animation.value + math.pi / 2,
);
canvas.drawPaint(Paint()..shader = gradient.createShader(rect));
}

@override
bool shouldRepaint(CustomPainter oldDelegate) => true;
}

Conclusión
Las animaciones de Flutter pueden ser simples o complejas, según tus necesidades. Al comprender los conceptos básicos de las animaciones, usar widgets preconstruidos como `AnimatedBuilder` y `CustomPaint`, y personalizar animaciones con curvas y controladores, puede crear animaciones hermosas y atractivas en sus aplicaciones de Flutter. Ya sea que esté creando una aplicación simple o compleja, las animaciones pueden ayudar a mejorar la experiencia del usuario y hacer que su aplicación se destaque del resto.