成为Flutter动画大师(一)

5,339 阅读3分钟

目录传送门:《Flutter快速上手指南》先导篇

在 Flutter 中,动画被分为两大类:Tween animation(补间动画)Physics-based animation(物理动画)

  1. Tween animation(补间动画)

    定义了动画的 初始状态终止状态,在指定的一段时间内完成状态的过度。

    期间可以以线性和非线性的方式控制过度的速度。

  2. Physics-based animation(物理动画)

    模拟现实世界物体运动的动画。比如:自由落体运动、加速度等。

不管是 TweenAnimation 还是 Physics-baseAnimation 最终都是通过计算出一系列的值来修改视图的属性,从而让视图 "动起来"。

1.一个动画的例子

class AnimPage2 extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return _AnimPage2();
  }
}

class _AnimPage2 extends State<AnimPage2> with TickerProviderStateMixin{

  var w = 100.0;
  var h = 100.0;

  Animation<double> animation;
  AnimationController animationController;


  @override
  void initState() {
      super.initState();
      // 创建 AnimationController,用于控制动画
      // 必须提供动画时间
      animationController = new AnimationController(vsync: this,duration: Duration(milliseconds: 1500));
      // 创建一个插值器,关联 AnimationController,返回一个新的 Animation 对象
      animation = Tween<double>(begin: 100.0, end: 100.0*2.0).animate(animationController);

      animationController.addListener((){
        // 当动画更新时会调用
        // 需要在这个函数中,调用 setState() 来触发视图刷新
        setState(() {
        });
      });
      // 开始播放动画
      animationController.forward();
  }

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(
        title: Text('Anim Demo 2'),
      ),
      body: Container(
        alignment: Alignment.center,
        child: SizedBox(
          // 获取插值器计算出的 value
          // 作为属性值
          width: animation.value,
          height: animation.value,
          child: Container(
            color: Colors.lightBlue,
          ),
        ),
      ),
    );
  }

  @override
  void dispose() {
    super.dispose();
    // 动画使用完成后必需要销毁
    animationController.dispose();
  }
}

看看效果:

2.动画中的核心角色

通过观察上面的例子,可以看出,在 Flutter 中实现动画效果需要涉及到的几个核心角色 🎭

  • Animation:动画对象。

  • AnimationController:继承自 Animation,但它能控制动画的播放、停止等。不需要时必须调用 dispose() 释放掉。

  • Animatable:插值器,用于产生动画过程中一系列的值。

在 Flutter 中,实现动画的核心是:

  1. 通过 插值器 产生一系列的值;

  2. 在值更新的回调监听 addListener() 中,通过 setState() 刷新视图;

  3. 插值器 产生的值设置到相应的视图属性上。

3.AnimationController

AnimationController 继承自 Animation

就像它的名字一样,它是动画的控制器,能够控制动画的播放、停止、释放等。

3.1 AnimationController 常用属性

属性类型说明
durationDuration动画时长
lowerBounddouble设置动画开始的最小值
upperBounddouble设置动画结束的最大值
vsyncTickerProvider用于监听系统的 Vsync 信号。当一个 Vsync 信息发出时,能够触发刷新数值,驱动动画

3.2 AnimationController 常用函数

  • forward()

    开始播放动画,调用它就没错了。

  • stop()

    停止动画。

  • reset()

    重置动画。

  • reverse()

    反向播放动画。必须处于正向动画播放完成的状态才有用。

  • dispose()

    释放动画占用资源。

  • fling()

    通过内部的 SpringSimulation 产生一系列值来驱动动画,其值的产生符合 胡克定律

    此时不需要再设置 duration,设置了也没用。

    在创建列表滑动动画时,你可能会用到它。

    这实际上就是一个 Physics-based animation

  • repeat()

    循环播放动画。

  • animateWith()

    通过 Simulation 来产生值驱动动画。

3.3 交错动画-同时播放多个动画

在 Flutter 中同时播放多个动画,只需要使用同一个 AnimationController 就行。

var animationController = new AnimationController(vsync: this,duration: Duration(milliseconds: 1500));
var animation1 = Tween<double>(begin: 100.0, end: 100.0*2.0).animate(animationController);
var animation2 = Tween<double>(begin: 0.0, end: 1.0).animate(animationController);

animationController.forward();

通过同一个 animationController 对象就可以同时控制 animation1animation2 两个动画了。

到此,读者应该已经能创建自己的动画 Demo 了。

目录传送门:《Flutter快速上手指南》先导篇

如何找到我?

传送门:CoorChice 的主页

传送门:CoorChice 的 Github