Animation沒有作什麼與動畫有關的事情,它只是記錄了動畫的「狀態」、當前的「值」和一些註冊回調接口的方法。app
abstract class Animation<T> extends Listenable implements ValueListenable<T> { const Animation(); // "值"變化的回調 @override void addListener(VoidCallback listener); @override void removeListener(VoidCallback listener); // 狀態回調 void addStatusListener(AnimationStatusListener listener); void removeStatusListener(AnimationStatusListener listener); // 動畫狀態 AnimationStatus get status; // 動畫當前「值」 @override T get value; bool get isDismissed => status == AnimationStatus.dismissed; bool get isCompleted => status == AnimationStatus.completed; //... }
Tween記錄了一個區間的begin和end。舉個例子來講:begin=100 end=200 ide
class Tween<T extends dynamic> extends Animatable<T> { //... // 起始值 T begin; // 結束值 T end; // 計算在特定區間某個時刻的返回值 // t是[0.0,1.0]在某個時刻的比例係數 @protected T lerp(double t) { assert(begin != null); assert(end != null); return begin + (end - begin) * t; } // 外部調用值的變換 @override T transform(double t) { if (t == 0.0) return begin; if (t == 1.0) return end; return lerp(t); } //... }
咱們在使用Tween的時候,必須調用Tween.animate()方法。其animate()方法是Tween繼承自Animatable<T>類而來的。函數
// 建立一個Animation anim = Tween<Offset>(begin: Offset(0, 0),end: Offset(0, 2),).animate(_controller); // 位移Tween類中,繼承自Animatable<T>類 Animation<T> animate(Animation<double> parent) { return _AnimatedEvaluation<T>(parent, this); } class _AnimatedEvaluation<T> extends Animation<T> with AnimationWithParentMixin<double> { //... @override final Animation<double> parent; // 這個變量就是Tween final Animatable<T> _evaluatable; @override T get value => _evaluatable.evaluate(parent); //... }
由此能夠得出animation.value的值來自Tween.evaluate().源碼分析
AnimationController的實現相比較其它的動畫核心類來講會比較複雜。那本文章就從兩個方面簡單分析一下AnimationController的實現。動畫
// AnimationController的聲明 class AnimationController extends Animation<double> with AnimationEagerListenerMixin, AnimationLocalListenersMixin, AnimationLocalStatusListenersMixin {
AnimationController能夠接收不少參數,其中最重要的就是@required TickerProvider vsync,由於它纔是動畫動起來的根本緣由(下面會講)。ui
AnimationController({ double value, this.duration,// 動畫執行時間 this.reverseDuration,// 動畫反向執行時的時間長度(默認和duration相同) this.debugLabel,//debug模式下使用的標籤 this.lowerBound = 0.0,// 動畫執行完一遍回到的值 this.upperBound = 1.0,// 動畫完成的值 this.animationBehavior = AnimationBehavior.normal,// 動畫行爲(一遍仍是重複執行) @required TickerProvider vsync, }) : assert(lowerBound != null), assert(upperBound != null), assert(upperBound >= lowerBound), assert(vsync != null), _direction = _AnimationDirection.forward { _ticker = vsync.createTicker(_tick);// 計時器 _internalSetValue(value ?? lowerBound); }
CurvedAnimation是一個非線性曲線的Animation,它繼承Animation,它與Animation的區別是在取值的時候按照特定非線性曲線函數生成的值。this
// 該函數的具體實現方式 @override double get value { final Curve activeCurve = _useForwardCurve ? curve : reverseCurve; final double t = parent.value; if (activeCurve == null) return t; if (t == 0.0 || t == 1.0) { assert(() { final double transformedValue = activeCurve.transform(t); final double roundedTransformedValue = transformedValue.round().toDouble(); if (roundedTransformedValue != t) { throw FlutterError( 'Invalid curve endpoint at $t.\n' 'Curves must map 0.0 to near zero and 1.0 to near one but ' '${activeCurve.runtimeType} mapped $t to $transformedValue, which ' 'is near $roundedTransformedValue.' ); } return true; }()); return t; } return activeCurve.transform(t); }
咱們建立動畫的時候,必需要傳遞一個TickerProvider參數,SingleTickerProviderStateMixin繼承TickerProvider。它自己有兩個做用:lua
@optionalTypeArgs mixin SingleTickerProviderStateMixin<T extends StatefulWidget> on State<T> implements TickerProvider { Ticker _ticker; // 建立Ticker @override Ticker createTicker(TickerCallback onTick) { assert(() { if (_ticker == null) return true; throw FlutterError( 'xxxxxxx' ); }()); _ticker = Ticker(onTick, debugLabel: kDebugMode ? 'created by $this' : null); return _ticker; } //... @override void didChangeDependencies() { // 關聯widget的生命週期,實際上傳給了Ticker if (_ticker != null) _ticker.muted = !TickerMode.of(context); super.didChangeDependencies(); } //... }
這時候咱們在外面經過anim.addListener(() {setState(() {});});不斷的視圖層進行重繪,則控件便動了起來。spa
參考文獻:一、感謝Flutter中文網提供的資料。二、感謝簡書博主debug