Flutter實戰(zhàn) Hero動畫

2021-03-08 18:01 更新

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

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

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

#示例

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

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

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

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

// 路由A
class HeroAnimationRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      alignment: Alignment.topCenter,
      child: InkWell(
        child: Hero(
          tag: "avatar", //唯一標記,前后兩個路由頁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", //唯一標記,前后兩個路由頁Hero的tag必須相同
          child: Image.asset("images/avatar.png"),
      ),
    );
  }
}

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

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

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

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號