Flutter 动画

动画类型

  • 补间动画
  • 基于物理基础的动画

常见动画模式

  • 列表或网格动画
  • 共享元素转换
  • 交织动画

基本动画概念和类

  • Animation,Flutter 动画库中的核心类,插入用于指导动画的值。
  • Animation 对象知道动画目前的状态(例如,是否开始,暂停,前进或倒退),但是对屏幕上显示的内容一无所知。
  • AnimationController 管理 Animation,范围为[0.0, 1.0]
  • CurvedAnimation 定义进程为非线性曲线。
  • Tween 为动画对象插入一个范围值。例如,Tween 可以定义插入值由红到蓝,或从 0 到 255。
  • 使用 Listener 和 StatusListener 监视动画状态变化。

CurvedAnimation 和 AnimationController(下面将会详细说明)都是 Animation 类型

动画通知

一个 Animation 对象可以有不止一个 Listener 和 StatusListener,用 addListener() 和 addStatusListener() 来定义。当动画值改变时调用 Listener。 Listener 最常用的操作是调用 setState() 进行重建。当一个动画开始,结束,前进或后退时,会调用 StatusListener,用 AnimationStatus 来定义

AnimationController

AnimationController 是用于控制动画的核心类。它提供了一些常用的方法和属性来管理动画的状态和行为。以下是一些常用的控制函数及其作用:

forward()
作用:使动画从当前值向前推进到结束值。
用法:通常在动画开始时调用

reverse()
作用:使动画从当前值向后推进到起始值。
用法:通常在动画结束后调用,以反向播放动画

stop()
作用:停止动画并保持在当前值。
用法:可以在需要时停止动画,例如用户交互时。

repeat({bool reverse = false})
作用:使动画在达到结束值后重新开始,可以选择是否反向播放。
用法:用于创建循环动画

forward(from)
作用:从指定的值开始向前推进动画。
用法:可以用于从动画的中间状态开始播放。

animateTo(double value, {Duration? duration, Curve curve = Curves.linear})
作用:将动画控制器的值动画到指定的值。
用法:用于在特定时间内平滑过渡到一个新的值

dispose()
作用:释放动画控制器占用的资源。
用法:在不再需要动画控制器时调用,通常在 dispose 方法中。

    动画示例

    初始化

    controller =
            AnimationController(duration: const Duration(seconds: 2), vsync: this);
        animation = CurvedAnimation(parent: controller, curve: Curves.easeIn)
          ..addStatusListener((status) {
            print('$status');
            if (status == AnimationStatus.completed) {
              controller.reverse();
            } else if (status == AnimationStatus.dismissed) {
              controller.forward();
            }
          });
    
        controller.forward();
    scaleAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(animation);
    
    class ScaleBasicAnimation extends StatelessWidget {
      const ScaleBasicAnimation(
          {required this.child, required this.scaleAnimation, super.key});
    
      final Widget child;
      final Animation<double> scaleAnimation;
    
      @override
      Widget build(BuildContext context) {
        return Center(
          child: ScaleTransition(
            scale: scaleAnimation,
            child: child,
          ),
        );
      }
    }
    
    ScaleBasicAnimation(scaleAnimation: scaleAnimation, child: const LogoWidget()),

    旋转

    rotationAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(animation);
    
    class RotationBasicAnimation extends StatelessWidget {
      const RotationBasicAnimation(
          {required this.child, required this.rotateAnimation, super.key});
    
      final Widget child;
      final Animation<double> rotateAnimation;
    
      @override
      Widget build(BuildContext context) {
        return Center(
          child: RotationTransition(
            turns: rotateAnimation,
            child: child,
          ),
        );
      }
    }
    
    RotationBasicAnimation(
                      rotateAnimation: rotationAnimation,
                      child: const LogoWidget()),

    淡入淡出

    opacityAnimation = Tween<double>(begin: 0.1, end: 1.0).animate(animation);
    
    class FadeBasicAnimation extends StatelessWidget {
      const FadeBasicAnimation(
          {required this.child, required this.opacityAnimation, super.key});
    
      final Widget child;
      final Animation<double> opacityAnimation;
    
      @override
      Widget build(BuildContext context) {
        return Center(
          child: FadeTransition(opacity: opacityAnimation, child: child),
        );
      }
    }
    FadeBasicAnimation(opacityAnimation: opacityAnimation,
                      child: const LogoWidget()),

    平移

     offsetAnimation = Tween<Offset>(
                begin: const Offset(0.0, 0.0), end: const Offset(0.0, 1.0))
            .animate(animation);
    
    class SildeBasicAnimation extends StatelessWidget {
      const SildeBasicAnimation(
          {required this.child, required this.offsetAnimation, super.key});
    
      final Widget child;
      final Animation<Offset> offsetAnimation;
    
      @override
      Widget build(BuildContext context) {
        return SlideTransition(
          position: offsetAnimation,
          child: child,
        );
      }
    }
    SildeBasicAnimation(offsetAnimation: offsetAnimation, child: const LogoWidget()),

    过渡Container

    AnimatedContainer(
                // Use the properties stored in the State class.
                width: _width,
                height: _height,
                decoration: BoxDecoration(
                  color: _color,
                  borderRadius: _borderRadius,
                ),
                // Define how long the animation should take.
                duration: const Duration(seconds: 1),
                // Provide an optional curve to make the animation feel smoother.
                curve: Curves.fastOutSlowIn,
              ),
            ),
    
      onPressed: () {
                // Use setState to rebuild the widget with new values.
                setState(() {
                  // Create a random number generator.
                  final random = Random();
    
                  // Generate a random width and height.
                  _width = random.nextInt(300).toDouble();
                  _height = random.nextInt(300).toDouble();
    
                  // Generate a random color.
                  _color = Color.fromRGBO(
                    random.nextInt(256),
                    random.nextInt(256),
                    random.nextInt(256),
                    1,
                  );
    
                  // Generate a random border radius.
                  _borderRadius =
                      BorderRadius.circular(random.nextInt(100).toDouble());
                });

    淡入淡出widget

    AnimatedOpacity(
              // If the widget is visible, animate to 0.0 (invisible).
              // If the widget is hidden, animate to 1.0 (fully visible).
              opacity: _visible ? 1.0 : 0.0,
              duration: const Duration(milliseconds: 500),
              // The green box must be a child of the AnimatedOpacity widget.
              child: Container(
                width: 200,
                height: 200,
                color: Colors.green,
              ),
            )

    留下评论

    您的电子邮箱地址不会被公开。 必填项已用 * 标注

    Index