flutter-動畫

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

v2-1bca865a9a7c1a49e3207e5780e5a865_1440w.jpg
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容