Flutter實(shí)戰(zhàn) Hero動(dòng)畫

2021-03-08 18:01 更新

Hero 指的是可以在路由(頁面)之間“飛行”的 widget,簡單來說 Hero 動(dòng)畫就是在路由切換時(shí),有一個(gè)共享的 widget 可以在新舊路由間切換。由于共享的 widget 在新舊路由頁面上的位置、外觀可能有所差異,所以在路由切換時(shí)會(huì)從舊路逐漸過渡到新路由中的指定位置,這樣就會(huì)產(chǎn)生一個(gè) Hero 動(dòng)畫。

你可能多次看到過 hero 動(dòng)畫。例如,一個(gè)路由中顯示待售商品的縮略圖列表,選擇一個(gè)條目會(huì)將其跳轉(zhuǎn)到一個(gè)新路由,新路由中包含該商品的詳細(xì)信息和“購買”按鈕。 在 Flutter 中將圖片從一個(gè)路由“飛”到另一個(gè)路由稱為 hero動(dòng)畫,盡管相同的動(dòng)作有時(shí)也稱為 共享元素轉(zhuǎn)換。下面我們通過一個(gè)示例來體驗(yàn)一下 hero 動(dòng)畫。

為什么要將這種可飛行的共享組件稱為 hero(英雄),有一種說法是說美國文化中的超人是可以飛的,那是美國人心中的大英雄,還有漫威中的超級英雄基本上都是會(huì)飛的,所以 Flutter 開發(fā)人員就對這種“會(huì)飛的 widget”就起了一個(gè)富有浪漫主義的名字 hero。當(dāng)然這種說法并非官方解釋,但卻很有意思。

#示例

假設(shè)有兩個(gè)路由A和B,他們的內(nèi)容交互如下:

A:包含一個(gè)用戶頭像,圓形,點(diǎn)擊后跳到B路由,可以查看大圖。

B:顯示用戶頭像原圖,矩形;

在AB兩個(gè)路由之間跳轉(zhuǎn)的時(shí)候,用戶頭像會(huì)逐漸過渡到目標(biāo)路由頁的頭像上,接下來我們先看看代碼,然后再解析:

  1. // 路由A
  2. class HeroAnimationRoute extends StatelessWidget {
  3. @override
  4. Widget build(BuildContext context) {
  5. return Container(
  6. alignment: Alignment.topCenter,
  7. child: InkWell(
  8. child: Hero(
  9. tag: "avatar", //唯一標(biāo)記,前后兩個(gè)路由頁Hero的tag必須相同
  10. child: ClipOval(
  11. child: Image.asset("images/avatar.png",
  12. width: 50.0,
  13. ),
  14. ),
  15. ),
  16. onTap: () {
  17. //打開B路由
  18. Navigator.push(context, PageRouteBuilder(
  19. pageBuilder: (BuildContext context, Animation animation,
  20. Animation secondaryAnimation) {
  21. return new FadeTransition(
  22. opacity: animation,
  23. child: Scaffold(
  24. appBar: AppBar(
  25. title: Text("原圖"),
  26. ),
  27. body: HeroAnimationRouteB(),
  28. ),
  29. );
  30. })
  31. );
  32. },
  33. ),
  34. );
  35. }
  36. }

路由B:

  1. class HeroAnimationRouteB extends StatelessWidget {
  2. @override
  3. Widget build(BuildContext context) {
  4. return Center(
  5. child: Hero(
  6. tag: "avatar", //唯一標(biāo)記,前后兩個(gè)路由頁Hero的tag必須相同
  7. child: Image.asset("images/avatar.png"),
  8. ),
  9. );
  10. }
  11. }

我們可以看到,實(shí)現(xiàn) Hero 動(dòng)畫只需要用Hero組件將要共享的 widget 包裝起來,并提供一個(gè)相同的 tag 即可,中間的過渡幀都是 Flutter Framework 自動(dòng)完成的。必須要注意, 前后路由頁的共享Hero的 tag 必須是相同的,F(xiàn)lutter Framework 內(nèi)部正是通過 tag 來確定新舊路由頁 widget 的對應(yīng)關(guān)系的。

Hero 動(dòng)畫的原理比較簡單,F(xiàn)lutter Framework 知道新舊路由頁中共享元素的位置和大小,所以根據(jù)這兩個(gè)端點(diǎn),在動(dòng)畫執(zhí)行過程中求出過渡時(shí)的插值(中間態(tài))即可,而感到幸運(yùn)的是,這些事情不需要我們自己動(dòng)手,F(xiàn)lutter 已經(jīng)幫我們做了!

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號