本例的代碼參考這裏。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();