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

2021-03-08 18:01 更新

Hero 指的是可以在路由(頁面)之間“飛行”的 widget,簡(jiǎn)單來說 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(英雄),有一種說法是說美國文化中的超人是可以飛的,那是美國人心中的大英雄,還有漫威中的超級(jí)英雄基本上都是會(huì)飛的,所以 Flutter 開發(fā)人員就對(duì)這種“會(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)路由頁的頭像上,接下來我們先看看代碼,然后再解析:

// 路由A
class HeroAnimationRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      alignment: Alignment.topCenter,
      child: InkWell(
        child: Hero(
          tag: "avatar", //唯一標(biāo)記,前后兩個(gè)路由頁Hero的tag必須相同
          child: ClipOval(
            child: Image.asset("images/avatar.png",
              width: 50.0,
            ),
          ),
        ),
        onTap: () {
          //打開B路由  
          Navigator.push(context, PageRouteBuilder(
              pageBuilder: (BuildContext context, Animation animation,
                  Animation secondaryAnimation) {
                return new FadeTransition(
                  opacity: animation,
                  child: Scaffold(
                    appBar: AppBar(
                      title: Text("原圖"),
                    ),
                    body: HeroAnimationRouteB(),
                  ),
                );
              })
          );
        },
      ),
    );
  }
}

路由B:

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

我們可以看到,實(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 的對(duì)應(yīng)關(guān)系的。

Hero 動(dòng)畫的原理比較簡(jiǎn)單,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)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)