flutter 路由全解

本教程前半部分屬于入門搀矫,后半部分屬于進階

1.routes 和navigator 的關系 ?

大部分應用程序都包含多個頁面,并希望用戶能從當前屏幕平滑過渡到另一個屏幕启泣。移動應用程序通常通過被稱為“屏幕”或“頁面”的全屏元素來顯示內容Flutter 中,這些元素被稱為路由(Route)束析,它們由導航器(Navigator)控件管理县习。導航器管理著路由對象的堆棧并提供管理堆棧的方法沟启,如 Navigator.pushNavigator.pop三娩,通過路由對象的進出棧來使用戶從一個頁面跳轉到另一個頁面鸿脓。

2. 怎么使用 抑钟?

(1)push方法

設置一個構造函數 (第二個page的初始方法)

 final String title;
 Page({this.title});

跳轉傳值

   Navigator.push(context,
        MaterialPageRoute(builder: (context) => Page(title: "題目")));

返回

   Navigator.pop(context);
(2) pushName方法

在初始化APP的地方MaterialApp,設置一個路由列表

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(  // 這個是標記
      home: MainPage(),
      debugShowCheckedModeBanner: false,
      routes: {  // 就是它
        '/page':(context) => Page()
       '/home':(context) => Home()
      },
    );
  }
}

在需要跳轉的時候

    Navigator.pushNamed(context, '/page');

這里有一個問題就是使用 Navigator.pushNamed 時無法直接給新頁面?zhèn)鲄狄翱蓿壳肮俜竭€沒有標準解決方案在塔,我知道的方案是在 onGenerateRoute 回調方法和arguments參數設置。

完整事例

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(

             //監(jiān)聽導航routes 數據  PassArguments
      onGenerateRoute: (settings) {

//對比路由名稱
        if (settings.name == PassArgumentsScreen.routeName) {
          final ScreenArguments args = settings.arguments;

           //返回  MaterialPageRoute 
          return MaterialPageRoute(
            builder: (context) {
              return PassArgumentsScreen(
                title: args.title,
                message: args.message,
              );
            },
          );
        }
      },
      title: 'Navigation with Arguments',
      home: HomeScreen(),
    );
  }
}

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Home Screen'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
           
                //設置一個button
            RaisedButton(
              child: Text("Navigate to screen that extracts arguments"),
              onPressed: () {
              

             // 設置傳值參數  arguments  /settings

                Navigator.push(
                  context,
                  MaterialPageRoute(
                    builder: (context) => ExtractArgumentsScreen(),
             
                    settings: RouteSettings(
                      arguments: ScreenArguments(
                        'Extract Arguments Screen',
                        'This message is extracted in the build method.',
                      ),
                    ),
                  ),
                );
              },
            ),
       
   
            RaisedButton(
              child: Text("Navigate to a named that accepts arguments"),
              onPressed: () {
              

                Navigator.pushNamed(
                  context,
                  PassArgumentsScreen.routeName,
                  arguments: ScreenArguments(
                    'Accept Arguments Screen',
                    'This message is extracted in the onGenerateRoute function.',
                  ),
                );
              },
            ),
          ],
        ),
      ),
    );
  }
}

// push界面
class ExtractArgumentsScreen extends StatelessWidget {
  static const routeName = '/extractArguments';

  @override
  Widget build(BuildContext context) {

 final ScreenArguments args = ModalRoute.of(context).settings.arguments;

    return Scaffold(
      appBar: AppBar(
        title: Text(args.title),
      ),
      body: Center(
        child: Text(args.message),
      ),
    );
  }
}

//接受界面
class PassArgumentsScreen extends StatelessWidget {
  static const routeName = '/passArguments';

  final String title;
  final String message;


  // MaterialApp widget.
  const PassArgumentsScreen({
    Key key,
    @required this.title,
    @required this.message,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: Center(
        child: Text(message),
      ),
    );
  }
}

// 設置任意參數
class ScreenArguments {
  final String title;
  final String message;

  ScreenArguments(this.title, this.message);
}

看懂了上面的原理當然可以簡化了虐拓。
定義要接受參數的界面的時候

// 定義接受的構造函數
final arguments心俗;
Page({this.arguments};

在上一界面?zhèn)髦档臅r候

Navigator.pushNamed(context,'/search',argument:{
    'id':'1123';   // 參數隨便寫
    'name':'sunny'
})

當然路由配置的時候要這樣

final routes = {
    'page':(context,{arguments})=>Page(arguments:arguments);
     'page':(context,{arguments})=>Page(arguments:arguments);
     'page':(context,{arguments})=>Page(arguments:arguments);
     'page':(context,{arguments})=>Page(arguments:arguments);  
}
final  String  name = setting.name;
final  Function  pagContentBuilder = this.routes[name];

當然你也可以吧參數和路由名稱都封裝到一個類中去 。說說思路蓉驹,全局單利路由文件設置好 城榛,設置路由對象 ,對象的個數和名稱提前固定 态兴,可以根據名稱隨時更改需要傳值的參數 狠持。 在界面跳轉前更改參數 ,傳入參數 瞻润,在界面跳轉后接受數據喘垂。
面對逆向的時候還可以加上加密措施和代碼混淆

//Routes.dart
import 'pa/material'  import '所有界面'
final routes = {
    'page':(context,{arguments})=>Page(arguments:arguments);
     'page':(context,{arguments})=>Page(arguments:arguments);
     'page':(context,{arguments})=>Page(arguments:arguments);
     'page':(context,{arguments})=>Page(arguments:arguments);  
}
// 生成路由回調的的固定寫法 
var onGenerateroute = (RounteSettings setting){
   final  String  name = setting.name;
   final  Function  pagContentBuilder = routes[name];
   if (pagContentBuilder != null){
      if(setting.arguments != null){

        final  Route route = MaterialpageRoute(
         buider:(context) => 
               PageContentBuilder(context,arguments:setting.arguments);
         )
         return route;
      }else{
           final  Route route = MaterialpageRoute(
         buider:(context) => 
               PageContentBuilder(context);
         )
         return route;
      }

   }
 
}


3.路由的命名規(guī)范 ?

樹狀結構命名法

'\' #主頁
'\home' #主頁 下 home界面
'\my' #主頁 下 my界面
'\home\name' #主頁 下 home界面 下name界面

3.initialRoute 的作用 ?

initialRoute 同樣是MaterialApp 的屬性 ,也就是相當于iOS里面的appdelegate部分绍撞,在全局只能設置一次 正勒。 在routes里面設置的路由都可以通過initialRoute來設置,也就是第一次啟動app時候傻铣,我們的初始界面是那個章贞。

路由的返回功能

Navigator.of(context).pop();

返回根路由/ 替換路由 在跳轉的時候使用替換路由,在返回的時候會直接返回到根目錄

Navigator.of(context).pushReplacementNamed('/firstPage');

或者直接返回根的代碼/ 沒有的話直接更改界面 非洲。

Navigator.of(context).pushAndRemoveUntil(
    // 中間的界面置為空鸭限,直到我們返回的頁面。
    newMaterialPageRutes(builder:context)=>new Tab bar(index : 1),
    (route)=>route==null;
)

(??????看到這里的都很厲害两踏,給你們點終極福利)??????

fluro的封裝使用

國外都流行用這個現在败京,下面是最權威的封裝

1設置一個全局的router,

形式多樣梦染,單例都可以,此處就放到Application類中了赡麦。

//application.dart
import 'package:fluro/fluro.dart';

class Application {
  static Router router;
}
2. 設置router 信息

引入handle文件,具體界面目錄

//routers.dart
import 'package:fluro/fluro.dart';
import 'package:flutter/material.dart';
import 'package:~/route_handlers.dart';

class Routes {
  static String root = '/';
//添加路由命名
  static String chatDetail = '/chat';

  static void configureRoutes(Router router) {
    router.notFoundHandler = new Handler(
      handlerFunc: (BuildContext context, Map<String, List<String>> params) {
        print('Route was not found.');
      }
    );
    router.define(root, handler: rootHandler);
//一條一條往后加處理方式
    router.define(chatDetail, handler: chatDetailHandler);
  }
}
3. 設置routerHandle 信息

具體每個頁面怎么處理都在這個文件中

//route_handlers.dart
import 'package:fluro/fluro.dart';
import 'package:flutter/material.dart';
import 'package:flutter_whatsapp/src/home.dart';


// 一條一條往后加,此處沒做任何處理
var rootHandler = new Handler(
  handlerFunc: (BuildContext context, Map<String, List<String>> params) {
    return new Home();
  }
);

 //此處解析了一個參數profileId
var chatDetailHandler = new Handler(
    handlerFunc: (BuildContext context, Map<String, List<String>> params) {
      int profileId = int.tryParse(params['profileId']?.first) ?? null;
// 此處調用構造方法
      return new DetailChatScreen(
        id: profileId,  
      );
    }
);

4.使用

MaterialApp中初始化


import 'package:fluro/fluro.dart';
import 'package:flutter/material.dart';
import 'package:config/application.dart';
import 'package:config/routes.dart';
import 'package:/src/home.dart';
import 'package:/src/values/colors.dart';



class FlutteredApp extends StatefulWidget {
  @override
  _FlutteredAppState createState() => _FlutteredAppState();
}

class _FlutteredAppState extends State<FlutteredApp> {

  _FlutteredAppState() {
    final router = new Router();
    Routes.configureRoutes(router);
    Application.router = router;
  }

  /// Default theme.
  static final ThemeData _defaultTheme = new ThemeData(
    primaryColor: primaryColor,
    accentColor: Colors.white,
    scaffoldBackgroundColor: scaffoldBgColor,
  );

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'setting',
      theme: _defaultTheme,
      onGenerateRoute: Application.router.generator,
    );
  }
}

調用

Application.router.navigateTo(
      context,
      "${Router.chatDetail}?profileId=${id}",
      transition: TransitionType.inFromRight,
    );

返回

  Navigator.of(context).pop();

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末隧甚,一起剝皮案震驚了整個濱河市车荔,隨后出現的幾起案子,更是在濱河造成了極大的恐慌戚扳,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,348評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件族吻,死亡現場離奇詭異帽借,居然都是意外死亡,警方通過查閱死者的電腦和手機超歌,發(fā)現死者居然都...
    沈念sama閱讀 90,122評論 2 385
  • 文/潘曉璐 我一進店門砍艾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人巍举,你說我怎么就攤上這事脆荷。” “怎么了懊悯?”我有些...
    開封第一講書人閱讀 156,936評論 0 347
  • 文/不壞的土叔 我叫張陵蜓谋,是天一觀的道長。 經常有香客問我炭分,道長桃焕,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,427評論 1 283
  • 正文 為了忘掉前任捧毛,我火速辦了婚禮观堂,結果婚禮上,老公的妹妹穿的比我還像新娘呀忧。我一直安慰自己师痕,他們只是感情好,可當我...
    茶點故事閱讀 65,467評論 6 385
  • 文/花漫 我一把揭開白布而账。 她就那樣靜靜地躺著胰坟,像睡著了一般。 火紅的嫁衣襯著肌膚如雪福扬。 梳的紋絲不亂的頭發(fā)上腕铸,一...
    開封第一講書人閱讀 49,785評論 1 290
  • 那天,我揣著相機與錄音铛碑,去河邊找鬼狠裹。 笑死,一個胖子當著我的面吹牛汽烦,可吹牛的內容都是我干的涛菠。 我是一名探鬼主播,決...
    沈念sama閱讀 38,931評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼俗冻!你這毒婦竟也來了礁叔?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,696評論 0 266
  • 序言:老撾萬榮一對情侶失蹤迄薄,失蹤者是張志新(化名)和其女友劉穎琅关,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體讥蔽,經...
    沈念sama閱讀 44,141評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡涣易,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,483評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了冶伞。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片新症。...
    茶點故事閱讀 38,625評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖响禽,靈堂內的尸體忽然破棺而出徒爹,到底是詐尸還是另有隱情,我是刑警寧澤芋类,帶...
    沈念sama閱讀 34,291評論 4 329
  • 正文 年R本政府宣布隆嗅,位于F島的核電站,受9級特大地震影響梗肝,放射性物質發(fā)生泄漏榛瓮。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,892評論 3 312
  • 文/蒙蒙 一巫击、第九天 我趴在偏房一處隱蔽的房頂上張望禀晓。 院中可真熱鬧,春花似錦坝锰、人聲如沸粹懒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽凫乖。三九已至,卻和暖如春弓颈,著一層夾襖步出監(jiān)牢的瞬間帽芽,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工翔冀, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留导街,地道東北人。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓纤子,卻偏偏與公主長得像搬瑰,于是被迫代替她去往敵國和親款票。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,492評論 2 348

推薦閱讀更多精彩內容