Flutter實(shí)戰(zhàn) 自定義路由切換動(dòng)畫

2021-03-08 18:01 更新

#9.3 自定義路由切換動(dòng)畫

我們?cè)诘诙隆奥酚晒芾怼币还?jié)中講過(guò):Material 組件庫(kù)中提供了一個(gè)MaterialPageRoute組件,它可以使用和平臺(tái)風(fēng)格一致的路由切換動(dòng)畫,如在 iOS 上會(huì)左右滑動(dòng)切換,而在 Android 上會(huì)上下滑動(dòng)切換。現(xiàn)在,我們?nèi)绻?Android 上也想使用左右切換風(fēng)格,該怎么做?一個(gè)簡(jiǎn)單的作法是可以直接使用CupertinoPageRoute,如:

 Navigator.push(context, CupertinoPageRoute(  
   builder: (context)=>PageB(),
 ));

CupertinoPageRoute是 Cupertino 組件庫(kù)提供的 iOS 風(fēng)格的路由切換組件,它實(shí)現(xiàn)的就是左右滑動(dòng)切換。那么我們?nèi)绾蝸?lái)自定義路由切換動(dòng)畫呢?答案就是PageRouteBuilder。下面我們來(lái)看看如何使用PageRouteBuilder來(lái)自定義路由切換動(dòng)畫。例如我們想以漸隱漸入動(dòng)畫來(lái)實(shí)現(xiàn)路由過(guò)渡,實(shí)現(xiàn)代碼如下:

Navigator.push(
  context,
  PageRouteBuilder(
    transitionDuration: Duration(milliseconds: 500), //動(dòng)畫時(shí)間為500毫秒
    pageBuilder: (BuildContext context, Animation animation,
        Animation secondaryAnimation) {
      return new FadeTransition(
        //使用漸隱漸入過(guò)渡,
        opacity: animation,
        child: PageB(), //路由B
      );
    },
  ),
);

我們可以看到pageBuilder 有一個(gè)animation參數(shù),這是 Flutter 路由管理器提供的,在路由切換時(shí)pageBuilder在每個(gè)動(dòng)畫幀都會(huì)被回調(diào),因此我們可以通過(guò)animation對(duì)象來(lái)自定義過(guò)渡動(dòng)畫。

無(wú)論是MaterialPageRoute、CupertinoPageRoute,還是PageRouteBuilder,它們都繼承自 PageRoute 類,而PageRouteBuilder其實(shí)只是PageRoute的一個(gè)包裝,我們可以直接繼承PageRoute類來(lái)實(shí)現(xiàn)自定義路由,上面的例子可以通過(guò)如下方式實(shí)現(xiàn):

  1. 定義一個(gè)路由類FadeRoute

   class FadeRoute extends PageRoute {
     FadeRoute({
       @required this.builder,
       this.transitionDuration = const Duration(milliseconds: 300),
       this.opaque = true,
       this.barrierDismissible = false,
       this.barrierColor,
       this.barrierLabel,
       this.maintainState = true,
     });

   
     final WidgetBuilder builder;

   
     @override
     final Duration transitionDuration;

   
     @override
     final bool opaque;

   
     @override
     final bool barrierDismissible;

   
     @override
     final Color barrierColor;

   
     @override
     final String barrierLabel;

   
     @override
     final bool maintainState;

   
     @override
     Widget buildPage(BuildContext context, Animation<double> animation,
         Animation<double> secondaryAnimation) => builder(context);

   
     @override
     Widget buildTransitions(BuildContext context, Animation<double> animation,
         Animation<double> secondaryAnimation, Widget child) {
        return FadeTransition( 
          opacity: animation,
          child: builder(context),
        );
     }
   }

  1. 使用FadeRoute

   Navigator.push(context, FadeRoute(builder: (context) {
     return PageB();
   }));

雖然上面的兩種方法都可以實(shí)現(xiàn)自定義切換動(dòng)畫,但實(shí)際使用時(shí)應(yīng)優(yōu)先考慮使用 PageRouteBuilder,這樣無(wú)需定義一個(gè)新的路由類,使用起來(lái)會(huì)比較方便。但是有些時(shí)候PageRouteBuilder是不能滿足需求的,例如在應(yīng)用過(guò)渡動(dòng)畫時(shí)我們需要讀取當(dāng)前路由的一些屬性,這時(shí)就只能通過(guò)繼承PageRoute的方式了,舉個(gè)例子,假如我們只想在打開新路由時(shí)應(yīng)用動(dòng)畫,而在返回時(shí)不使用動(dòng)畫,那么我們?cè)跇?gòu)建過(guò)渡動(dòng)畫時(shí)就必須判斷當(dāng)前路由isActive屬性是否為true,代碼如下:

@override
Widget buildTransitions(BuildContext context, Animation<double> animation,
    Animation<double> secondaryAnimation, Widget child) {
 //當(dāng)前路由被激活,是打開新路由
 if(isActive) {
   return FadeTransition(
     opacity: animation,
     child: builder(context),
   );
 }else{
   //是返回,則不應(yīng)用過(guò)渡動(dòng)畫
   return Padding(padding: EdgeInsets.zero);
 }
}

關(guān)于路由參數(shù)的詳細(xì)信息讀者可以自行查閱 API 文檔,比較簡(jiǎn)單,不再贅述。

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

掃描二維碼

下載編程獅App

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

編程獅公眾號(hào)