本例的代码参考这里。git
动画处理的基本原理是,对组件(widget)的某个或某组属性设置一组连续变化的值,这些值在必定时间间隔内不断被应用到该属性上,使得组件的外观看上去在进行平滑而连续的变更。github
例如2秒内每隔0.1s将一个组件的x轴坐标加1,那么该组件看上去就是从左至右移动了2秒共20个单位。ide
具体到Flutter,动画处理主要分为三个部分:动画
上述三大组件,控制了整个动画的运行。用文字描述,其流程主要包括:ui
AnimationController是一个特殊的Animation对象。建立一个AnimationController时,须要传递一个vsync参数。设置此参数的目的,是但愿屏幕每一帧画面变化时可以被通知到。也就是说,屏幕刷新的每一帧,AnimationController都会生成一个新的值(一样也意味着,若是在屏幕外那么就不被触发)。这样动画组件就可以完成一个连续平滑的动画动做。this
Tickers can be used by any object that wants to be notified whenever a frame triggers。
AnimationControler一般是在一个StatefulWidget中被声明,而且附带一个叫作SingleTickerProviderStateMixin的Mixin(缘由就在上面说的,要设置vsync参数)。spa
class AnimationDemo extends StatefulWidget { AnimationDemoState createState() => AnimationDemoState(); } class AnimationDemoState extends State<AnimationDemo> with SingleTickerProviderStateMixin { AnimationController controller; @override void initState() { super.initState(); controller = AnimationController(duration: Duration(milliseconds: 2000), vsync: this); ... } @override void dispose() { controller.dispose(); // 离开时须要销毁controller super.dispose(); } ... }
当Animation和Tween的设置完成后,简单调用controller.forward()便可开始动画。code
Tween就是要改变的属性值的变更范围。它能够是任意的属性类如Offset或者Color,最多见的是double。对象
... AnimationController controller; Tween<double> slideTween = Tween(begin: 0.0, end: 20.0); ...
Animation对象自己能够看作是动画中全部变化值的一个集合。它包含了变化区间内的全部可取值,并返回给动画组件当前的变更值。图片
Animation在使用中要设置的,是他的变更速率,如Curves.linear(线性变化)。
... AnimationController controller; Tween<double> slideTween = Tween(begin: 0.0, end: 20.0); Animation<double> animation; @override void initState() { super.initState(); ... animation = slideTween.animate(CurvedAnimation(parent: controller, curve: Curves.linear)); } ...
为了说明简单,在build方法中嵌套两个Container组件,外部容器Container的paddingLeft跟随动画变更,达到移动内部Container的目的。
class AnimationDemoState extends State<AnimationDemo> with SingleTickerProviderStateMixin { ... @override Widget build(BuildContext context) { return Container( width: 200, alignment: Alignment.centerLeft, padding: EdgeInsets.only(left: animation.value), child: Container( color: Colors.blue, width: 80, height: 80, ), ); } }
在启动动画以前有一个Flutter的基本概念要说明。作过React的同窗很清楚,要想render方法从新执行,要么props有更新要么state有更新。在Flutter也一样如此,build方法一样依赖于state的更新才能从新执行。
在AnimationController的说明中,咱们知道由于设置了vsync因此屏幕刷新的每一帧都会更新它的值。因此能够在Controller上加上一个listener,每次有update都调用一下setState,以此达到从新渲染UI的目的。
... @override void initState() { ... animation.addListener(() => this.setState(() {})); controller.repeat(); // 动画重复执行 }
调用controller.repeat()方法,动画会被反复执行。若是想只执行一次,那么可使用controller.forward();