Flutter(四)靜態(tài)路由與動態(tài)路由

因?yàn)楣P者本身主要從事是Android開發(fā),所以很多角度都是作為一個Android開發(fā)者學(xué)習(xí)Flutter的角度出發(fā),IOS或者H5的開發(fā)同學(xué)可以選擇性閱讀

目錄

前言

做Android開發(fā)的時候,要打開一個新的頁面,你得知道你的目標(biāo)頁面對象,然后初始化一個Intent或,再通過startActivity來打開一個新的頁面,不能跟web一樣,直接丟一個鏈接地址就跳轉(zhuǎn)到新的頁面。而Flutter的framework提供了類似路由跳轉(zhuǎn)的實(shí)現(xiàn)

靜態(tài)路由

  1. 靜態(tài)路由的注冊

MaterialApp組件中有一個字段routes參數(shù)來注冊路由,但是這里注冊的路由是靜態(tài)的,它不可以向下一個頁面?zhèn)鬟f參數(shù)

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: NavigatorPage(),
      routes: <String, WidgetBuilder>{
        '/router/first': (BuildContext context) => FirstPage(),
        '/router/second': (BuildContext context) => SecondPage()
      },
    );
  }
}
  1. 通過靜態(tài)路由跳轉(zhuǎn)(類似于Android中的startActivity
Navigator.pushNamed(context, "/router/first");
  1. 帶返回值的靜態(tài)路由(類似于Android中的onActivityResult

注意:靜態(tài)路由不能傳遞參數(shù)給下一個頁面,但是可以接收返回參數(shù)

Navigator.pushNamed(context, routeName).then((value){
  //可以在這使用返回值value
});
  1. 返回上一個頁面(類似于Android中的setResult + finish
Navigator.of(context).pop('這是要返回給上一個頁面的數(shù)據(jù)');

動態(tài)路由

  1. 動態(tài)路由無需在routes中注冊即可直接使用
Navigator.push(context, new MaterialPageRoute(builder: (context) {
  return new FirstPage(title: '這是要傳遞給下一個頁面的參數(shù)');
}));
  1. 動態(tài)路由切換動畫

Material庫中提供了一個MaterialPageRoute,它可以使用和平臺風(fēng)格一致的路由切換動畫,如在iOS上會左右滑動切換,而在Android上會上下滑動切換。如果在Android上也想使用左右切換風(fēng)格,可以直接使用CupertinoPageRoute, 如:

Navigator.push(context, new CupertinoPageRoute(builder: (context) {
  return new FirstPage();
}));

如果想自定義路由切換動畫,可以使用PageRouteBuilder,例如我們想以漸隱漸入動畫來實(shí)現(xiàn)路由過渡:

Navigator.push(context, PageRouteBuilder(
      transitionDuration: Duration(milliseconds: 500), //動畫時間為500毫秒
      pageBuilder: (BuildContext context, Animation animation,
          Animation secondaryAnimation) {
        return new FadeTransition( //使用漸隱漸入過渡, 
          opacity: animation,
          child: FirstPage() 
        );
      }));
}),

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

無論是MaterialPageRoute、CupertinoPageRoute,還是PageRouteBuilder,它們都繼承自PageRoute類,而PageRouteBuilder其實(shí)只是PageRoute的一個包裝,我們可以直接繼承PageRoute類來實(shí)現(xiàn)自定義路由,如下所示

定義一個路由類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),
     );
  }
}

使用FadeRoute

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

雖然上面的兩種方法都可以實(shí)現(xiàn)自定義切換動畫,但實(shí)際使用時應(yīng)考慮優(yōu)先使用PageRouteBuilder,這樣無需定義一個新的路由類,使用起來會比較方便。但是有些時候PageRouteBuilder是不能滿足需求的,例如在應(yīng)用過渡動畫時我們需要讀取當(dāng)前路由的一些屬性,這時就只能通過繼承PageRoute的方式了,舉個例子,假如我們只想在打開新路由時應(yīng)用動畫,而在返回時不使用動畫,那么我們在構(gòu)建過渡動畫時就必須判斷當(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)用過渡動畫
   return Padding(padding: EdgeInsets.zero);
 }
}

總結(jié)

靜態(tài)路由和動態(tài)路由最大的差距就是動態(tài)路由可以向下一個頁面?zhèn)鬟f參數(shù),而靜態(tài)理由不可以。且動態(tài)路由可以設(shè)置路由切換的動畫

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容