Flutter 路由動畫Offset小記

剛剛看了一下flutter的路由動畫文檔,地址是:page-route-animation html

PageRouteBuilder(
    pageBuilder: (context, animation, secondaryAnimation) => Page2(),
    transitionsBuilder: (context, animation, secondaryAnimation, child) {
      var begin = Offset(0.0, -1.0);
      var end = Offset.zero;
      var curve = Curves.ease;

      var tween = Tween(begin: begin, end: end).chain(CurveTween(curve: curve));

      return SlideTransition(
        position: animation.drive(tween),
        child: child,
      );
    },
  )
複製代碼

針對動畫,學習了兩點:api

  1. Flutter offset的值是怎麼回事,1 0 -1分別表明什麼,我整理了一下,如圖:

我來解讀一下,

1. 頁面顯示在屏幕時,Offset的dx dy均爲0;
2. 若是須要動畫頁面從屏幕底部彈出,則應該是dy=1 到 dy=0;
3. 若是須要動畫頁面從右側推入到屏幕,則應該是dx=1 到 dx=0;
4. 若是須要動畫頁面從屏幕頂部彈出,則應該是dy=0 到 dy=-1
5. 其餘相似
複製代碼

建議你們使用文檔裏的案例操做實驗一下,加深印象。學習了這個,在寫動畫時就不會出現亂套的狀況了。bash

  1. secondaryAnimation是幹嗎用的呢?

寫過安卓的都清楚有進場和出場動畫,overridexxxx,那flutter只經過上面這段代碼怎麼實現出場,就給了一個child,非常奇怪。而後我發現secondaryAnimation還沒用,是幹嗎的?翻閱的一些文檔: buildTransitionsmarkdown

看到了使用方式:ide

transitionsBuilder: (
      BuildContext context,
      Animation<double> animation,
      Animation<double> secondaryAnimation,
      Widget child,
  ) {
    return SlideTransition(
      position: AlignmentTween(
        begin: const Offset(0.0, 1.0),
        end: Offset.zero,
      ).animate(animation),
      child: SlideTransition(
        position: TweenOffset(
          begin: Offset.zero,
          end: const Offset(0.0, 1.0),
        ).animate(secondaryAnimation),
        child: child,
      ),
    );
  }
複製代碼

剛看到我是很驚訝的,這是個怎麼操做法?進出都套在了一個child上,到底怎麼運行的呢?一開始我猜測難道是源碼使用的地方會取出child的child?看了源碼後,我以爲設計真巧妙!!oop

首先介紹下這兩個動畫常量(animation.dart中,目的就是保持動畫終止位置和保持動畫起始位置):學習

kAlwaysCompleteAnimation // The animation is stopped at the end測試

kAlwaysDismissedAnimation // The animation is stopped at the beginning動畫

看到這裏你們可能會有點明白了,兩個animation是否是用上面兩個常量,來切換使用作到每次只運行一個的呢?ui

而後我用下面的動畫(一段動畫,新頁面從右側屏幕滑入,舊頁面從屏幕左側滑出),打印了一下對應的回調:

SlideTransition(
      position: Tween<Offset>(
        begin: const Offset(1.0, 0.0),
        end: Offset.zero,
      ).animate(animation),
      child: SlideTransition(
        position: Tween<Offset>(
          begin: Offset.zero,
          end: const Offset(-1.0, 0.0),
        ).animate(secondAnimation),
        child: child,
      ),
    )
複製代碼

獲得的log,簡化後:

animation sencondaryAnimation
AnimationController#1c77c(▶ 0.335 kAlwaysDismissedAnimation
AnimationController#fc1fe(⏭ 1.000 AAnimationController#1c77c(▶ 0.335
AnimationController#1c77c(▶ 0.535 kAlwaysDismissedAnimation
AnimationController#fc1fe(⏭ 1.000 AAnimationController#1c77c(▶ 0.535
AnimationController#1c77c(⏭ 1.000 kAlwaysDismissedAnimation
AnimationController#fc1fe(⏭ 1.000; AnimationController#1c77c⏭ 1.000

先只看#1c77c這個animation:

發現第一個參數是從0-1作的動畫,第二個參數是保持不變在start狀態即Offset.zero,即經過改變第一個widge的位置,來實現界面從右側滑入,第二個widget一直保持可見狀態。

再來看下fc1fe這個animation,發現這個動畫是第一個widge保持在end狀態即Offset.zero(屏幕上),第二個動畫是從0-1運行,即offset.dx從0 -> -1,也就是頁面從屏幕往左側滑出的動畫。

由以上,咱們能夠得出結論,animation參數值是用來給新push的頁面作進場動畫的,secondaryAnimation是給前頁面作出廠動畫的,靈活運用兩個動畫的變化值來實現動畫,參數只須要一個child便可,我也從中學習了一種新的思路,建議你們也測試感覺下。

相關文章
相關標籤/搜索