過場動畫
過場動畫也就是切換路由時的動畫
這個東西有幾種方案可以做
- 繼承
PageRoute
來做, 複寫 5 個抽象方法, 並抽象buildTransitions
- 繼承已有的系統類, 比如 MaterialPageRoute 或者 CupertinoPageRoute
- 一勞永逸的方案, 使用
PageTransitionsTheme
類結合 MaterialApp 的 theme 的pageTransitionsTheme
屬性
前兩種目前網路上也有一些人做了分享, 但第三種好像很少有人使用, 我這裡就來說一下PageTransitionsTheme
的用法
這東西有如下的好處:
- 設定一次, 你所有的
MaterialPageRoute
都可以生效 - 對於命名路由, 也就是
pushNamed
體系的也有效
先分析下原始碼
為啥分析原始碼? 因為如果上來就用顯得不高階
先找一個大家都知道的切入點, 一般的過場動畫都是用的 Navigator.push
方法來實現的

看看方法裡的實現, 會發現很多常見的東西, 比如, 每一個 Route 都有自己的 OverlayEntry
然後會有一個 install 方法

而實際呼叫中, 這個 Overlay 會被插入到 Overlay 棧內, 從而在介面上顯示




經過這一串的呼叫, 就把 Navigator push 和 Route 關聯到了一起, 那麼 theme 是怎麼和 Route 關聯起來的呢, 我們進入 MaterialPageRoute 看一下

我們看到, 這裡是從 Theme 中找到 pageTransitionsTheme, 然後呼叫 pageTransitionsTheme 的 buildTransitions 方法來完成構建, 所以這就是我們可以在 theme 中一次修改, 多處生效的主因了
如何使用
前面檢視到了原始碼是如何關聯到 pageTransitionsTheme
屬性的, 我們接著就是該自定義的時候了
修改自己的 MyApp, 修改pageTransitionsTheme
屬性
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
pageTransitionsTheme: PageTransitionsTheme(
builders: <TargetPlatform, PageTransitionsBuilder>{
TargetPlatform.iOS: createTransition(),
TargetPlatform.android: createTransition(),
},
),
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
複製程式碼
使用系統提供的一些動畫
PageTransitionsBuilder createTransition() {
return FadeUpwardsPageTransitionsBuilder();
}
複製程式碼
效果如下:

根據註釋, sdk 中有如下幾種動畫

其中FadeUpwardsPageTransitionsBuilder
對應安卓預設的, PageTransitionsBuilder
自然是對應的 iOS
ZoomPageTransitionsBuilder:

OpenUpwardsPageTransitionsBuilder:

自定義
除了已有的, 我們還可以自定義動畫, 可以配合 animation元件來完成酷炫的動畫效果, 具體的可以檢視官網動畫部分介紹
自定義 MyPageTransitionsBuilder
import 'package:flutter/material.dart';
PageTransitionsBuilder createTransition() {
// return FadeUpwardsPageTransitionsBuilder();
// return OpenUpwardsPageTransitionsBuilder();
// return ZoomPageTransitionsBuilder();
return MyPageTransitionsBuilder();
}
class MyPageTransitionsBuilder extends PageTransitionsBuilder {
@override
Widget buildTransitions<T>(
PageRoute<T> route,
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child) {
return ScaleTransition(
scale: animation,
child: RotationTransition(
turns: animation,
child: child,
),
);
}
}
複製程式碼
效果如下

後記
有問題請在本人部落格下留言(github 登陸即可)