flutter動畫
1.動畫原理:在一段時間內(nèi)快速的多次改變UI外觀,由于人眼會產(chǎn)生視覺暫留所以最終看到的就是一個連續(xù)的動畫。
UI的一次改變稱為一個動畫幀,對應一次屏幕刷新。
FPS:幀率,每秒的動畫幀數(shù)。
flutter動畫分為兩類:
- 補間動畫
- 物理動畫
常見動畫模式:
- list、grid中的動畫:例如一些元素的添加或者刪除。
- 轉(zhuǎn)場動畫
- 交錯動畫
基本的動畫概念與類:
Animation
是一個抽象類,主要的功能是保存動畫的值和狀態(tài)。常用的一個Animation類是Animation< double >,是一個在一段時間內(nèi)依次生成一個區(qū)間之間的值的類,可以是線性或者曲線或者其他。
可以生成除double之外的其他類型值,如:Animation< Color > 或 Animation< Size >。
AnimationController
是一個動畫控制器,控制動畫的播放狀態(tài),在屏幕刷新的每一幀,就會生成一個新的值。
包含動畫的啟動forward()、停止stop() 、反向播放 reverse()等方法,在給定的時間段內(nèi)線性的生成從0.0到1.0(默認區(qū)間)的數(shù)字。
- 使用Listeners和StatusListeners監(jiān)聽動畫狀態(tài)改變。
AnimationController controller = AnimationController(
duration: Duration(milliseconds: 2000), vsync: this);
Curve
curve:描述動畫的曲線過程。
curvedAnimation:指定動畫的曲線。
final CurvedAnimation curve =
new CurvedAnimation(parent: controller, curve: Curves.easeIn);
常用Curve:
- linear:勻速的
- decelerate:勻減速
- ease:開始減速后減速
- easeIn:開始慢后快
- easeOut:開始快后慢
- easeInOut:開始慢加速再減速
Tween
繼承自Animatable< T >,表示的就是一個 Animation 對象的取值范圍,只需要設置開始和結(jié)束的邊界值(值也支持泛型)。 它唯一的工作就是定義輸入范圍到輸出范圍的映射。
例如,Tween可能會生成從紅到藍之間的色值,或者從0到255。
final Tween colorTween =
new ColorTween(begin: Colors.transparent, end: Colors.black54);
Tween.animate:返回一個Animation。
映射過程:
1). Tween.animation通過傳入 aniamtionController 獲得一個_AnimatedEvaluation 類型的 animation 對象(基類為 Animation), 并且將 aniamtionController 和 Tween 對象傳入了 _AnimatedEvaluation 對象。
Animation<T> animate(Animation<double> parent) {
return _AnimatedEvaluation<T>(parent, this);
}
2). animation.value方法即是調(diào)用 _evaluatable.evaluate(parent)方法, 而 _evaluatable 和 parent 分別為 Tween 對象和 AnimationController 對象。
T get value => _evaluatable.evaluate(parent);
....
class _AnimatedEvaluation<T> extends Animation<T> with AnimationWithParentMixin<double> {
_AnimatedEvaluation(this.parent, this._evaluatable);
3). 這里的 animation 其實就是前面的 AnimationController 對象, transform 方法里面的 animation.value則就是 AnimationController 線性生成的 0.0~1.0 直接的值。 在 lerp 方法里面我們可以看到這個 0.0~1.0 的值被映射到了 begin 和 end 范圍內(nèi)了。
T evaluate(Animation<double> animation) => transform(animation.value);
T transform(double t) {
if (t == 0.0)
return begin;
if (t == 1.0)
return end;
return lerp(t);
}
T lerp(double t) {
assert(begin != null);
assert(end != null);
return begin + (end - begin) * t;
}
vsync
接收一個TickerProvider類型的對象,它的主要職責是創(chuàng)建Ticker。
防止屏幕外動畫消耗資源。
流程圖:
[圖片上傳失敗...(image-115b94-1636441483468)]
總結(jié):
過程:
- TickerProvider 會創(chuàng)建一個 Ticker, 并將_tick(TickerCallback 類型)回調(diào)方法綁定到了 這個 Ticker, 這樣 AnimationController 就將回調(diào)方法 _tick 和 Ticker 綁定了。
- Ticker 會在 start 函數(shù)內(nèi)將_tick 被綁定到 SchedulerBinding 的幀回調(diào)方法內(nèi)。
- SchedulerBinding 則是在構造方法中將自己的 _handleBeginFrame 函數(shù)和 window 的 onBeginFrame 綁定了回調(diào)。 這個回調(diào)會在屏幕需要準備顯示幀之前回調(diào)。
- 在 AnimationController 的回調(diào)當中, 計算當前的的_value 值, 更新 Animation Status 的狀態(tài), 判斷是否動畫已經(jīng)結(jié)束。 最后通過 notifyListeners 和_checkStatusChanged 方法通知給監(jiān)聽器 value 和 AnimationStatus 的變化。
回調(diào):
ui.window.onBeginFrame = handleBeginFrame;
ui.window.onDrawFrame = handleDrawFrame;
- window調(diào)用SchedulerBinding的_handleBeginFrame方法
- SchedulerBinding調(diào)用Ticker的_tick方法
- Ticker調(diào)用 AnimationController的_tick的方法,
- animationContoller通知監(jiān)聽器
- 而監(jiān)聽器調(diào)用widget的setStatus方法來調(diào)用build更新
- build使用了Animation對象當前的值來繪制動畫幀
用AnimatedWidget簡化
不使用addListener()和setState()來給widget添加動畫。
使用AnimatedWidget,將widget分離出來,創(chuàng)建一個可重用動畫的widget,AnimatedWidget中會自動調(diào)用addListener()和setState()
class AnimatedImage extends AnimatedWidget {
AnimatedImage({Key key, Animation<double> animation})
: super(key: key, listenable: animation);
Widget build(BuildContext context) {
final Animation<double> animation = listenable;
return new Center(
child: Image.asset("imgs/avatar.png",
width: animation.value,
height: animation.value
),
);
}
}
常用控件
AnimatedModalBarrier、DecoratedBoxTransition、FadeTransition、PositionedTransition、RelativePositionedTransition、RotationTransition、ScaleTransition、SizeTransition、SlideTransition
AnimatedBuilder重構
如何渲染過渡,把渲染過程也抽象出來:
AnimatedBuilder的示例包括: BottomSheet、 PopupMenu、ProgressIndicator、RefreshIndicator、Scaffold、SnackBar、TabBar。
轉(zhuǎn)場動畫
MaterialPageRoute:平臺風格一致的路由切換動畫
CupertinoPageRoute:左右切換風格
Navigator.push(context, CupertinoPageRoute(
builder: (context)=>PageB(),
));
自定義:PageRouteBuilder
交織動畫
1.要創(chuàng)建交織動畫,需要使用多個動畫對象(Animation)。
2.一個AnimationController控制所有的動畫對象。
3.給每一個動畫對象指定時間間隔(Interval)
AnimatedSwitcher
可以同時對其新、舊子元素添加顯示、隱藏動畫.
當AnimatedSwitcher的child發(fā)生變化時(類型或Key不同),舊child會執(zhí)行隱藏動畫,新child會執(zhí)行執(zhí)行顯示動畫。
希望大家支持一下,感謝
https://itunes.apple.com/cn/app/id1581903089
