剛剛看了一下flutter的路由動畫文件,地址是:page-route-animation
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,
);
},
)
複製程式碼
針對動畫,學習了兩點:
- 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. 其他類似
複製程式碼
建議大家使用文件裡的案例操作實驗一下,加深印象。學習了這個,在寫動畫時就不會出現亂套的情況了。
- secondaryAnimation是幹嘛用的呢?
寫過安卓的都清楚有進場和出場動畫,overridexxxx,那flutter只通過上面這段程式碼怎麼實現出場,就給了一個child,很是奇怪。然後我發現secondaryAnimation還沒用,是幹嘛的?翻閱的一些文件: buildTransitions
看到了使用方式:
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?看了原始碼後,我覺得設計真巧妙!!
首先介紹下這兩個動畫常量(animation.dart中,目的就是保持動畫終止位置和保持動畫起始位置):
kAlwaysCompleteAnimation // The animation is stopped at the end
kAlwaysDismissedAnimation // The animation is stopped at the beginning
看到這裡大家可能會有點明白了,兩個animation是不是用上面兩個常量,來切換使用做到每次只執行一個的呢?
然後我用下面的動畫(一段動畫,新頁面從右側螢幕滑入,舊頁面從螢幕左側滑出),列印了一下對應的回撥:
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即可,我也從中學習了一種新的思路,建議大家也測試感受下。