https://blog.csdn.net/senkai123/article/details/102948524
Flutter 命名路由、路由組、路由退出、路由堆棧
在flutter中需要進行頁面跳轉,也是需要用到路由Route,關鍵Navigator與Route,Navigator負責單元Route路由,壓入和彈出,單元路由也就是我們需要跳轉頁面 ,比如HomePage()
Navigator關鍵使用的4個屬性
•initialRoute: 初始路由的,也就是進入APP,默認頁面
•onGenerateRoute: 路由攔截器
•onUnknownRoute: 找不到頁面,也就是404
•routes : 路由集合,也就在執行路由跳轉的時候,會到路由集合里面的子路由進行匹配,如果匹配 到那么就調整到指定頁面
路由跳轉 方式:
1.通過路由名打開新路由頁面
通過路由名稱來打開新路由,可以使用Navigator 的pushNamed方法:
Future pushNamed(BuildContext context, String routeName,{Object arguments})
1
調用:
onPressed: () {
//不帶參數
Navigator.pushNamed(context, "new_page");
//帶參數,可以指定單個參數,或者多個, arguments: {}
Navigator.of(context).pushNamed("new_page", arguments: "hi");
},
頁面承接帶過來的參數
String tmp = ModalRoute.of(context).settings.arguments.toString();
1
2.匿名路由打開新路由頁面
Navigator.push( context, MaterialPageRoute(builder: (context) {
return HomePage();
}));
傳參:
final Map<String, WidgetBuilder> _routes = {
'/sign': (context, {arguments}) => SignPage(arguments: arguments),
};
接參:
class SignPage extends StatelessWidget {
final Map arguments;
SignPage({Key key, this.arguments}) : super(key: key) {
}
@override
Widget build(BuildContext context) {
String tmp2 = this.arguments.toString();
}
}
路由集合(路由表)與onGenerateRoute的關系
onGenerateRoute接受一個 Route 工廠函數
final RouteFactory onGenerateRoute;
1
路由攔截源碼,從攔截到路由之后,首先從路由表中拿到路由的 builder,如果能夠拿到 builder,則判斷是否存在 RouteSettings,如果存在則直接通關構造函數的 arguments 傳遞給頁面 Page Widget。本質就是按照路由名字匹配路由表,然后跳轉到正確頁面中
Route _routeGenerator(RouteSettings settings) {
final String name = settings.name;
final Function pageBuilder = this._routes[name];
if (pageBuilder != null) {
if (settings.arguments != null) {
// 如果透傳了參數
return MaterialPageRoute(
builder: (context) =>
pageBuilder(context, arguments: settings.arguments));
} else {
// 沒有透傳參數
return MaterialPageRoute(builder: (context) => pageBuilder(context));
}
}
return MaterialPageRoute(builder: (context) => HomeContent());
}
路由的使用方式
第一個種,初始化執行路線,initialRoute -> onGenerateRoute -> onUnknownRoute, 路由跳轉Navigator.pushNamed(context, “secondPage”); ,之后會到onGenerateRoute ,進行路由攔截匹配,如果能正確匹配到,那么跳轉到指定頁面
例子:
import 'package:flutter/material.dart';
class NavigatorPage extends StatefulWidget {
@override
_NavigatorPageState createState() => _NavigatorPageState();
}
class _NavigatorPageState extends State<NavigatorPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Navigator'),
),
body: Column(
children: <Widget>[
Text('Navigator的高度為infinity'),
Text('如果直接父級非最上級也是infinity會產生異常'),
Container(
height: 333,
color: Colors.amber.withAlpha(111),
child: Navigator( // Navigator
initialRoute: '/abc',
onGenerateRoute: (val) {
RoutePageBuilder builder;
switch (val.name) {
case '/abc':
builder = (BuildContext nContext, Animation<double> animation, Animation<double> secondaryAnimation) => Column(
// 並沒有在 MaterialApp 中設定 /efg 路由
// 因為Navigator的特性 使用nContext 可以跳轉 /efg
children: <Widget>[
Text('呵呵呵'),
RaisedButton(
child: Text('去 /efg'),
onPressed: () {
Navigator.pushNamed(nContext, '/efg');
},
)
],
);
break;
case '/efg':
builder = (BuildContext nContext, Animation<double> animation, Animation<double> secondaryAnimation) => Row(
children: <Widget>[
RaisedButton(
child: Text('去 /hhh'),
onPressed: () {
Navigator.pushNamed(nContext, '/hhh');
},
)
],
);
break;
default:
builder = (BuildContext nContext, Animation<double> animation, Animation<double> secondaryAnimation) => Center(
child: RaisedButton(
child: Text('去 /abc'),
onPressed: () {
Navigator.pushNamed(nContext, '/abc');
},
)
);
}
return PageRouteBuilder(
pageBuilder: builder,
// transitionDuration: const Duration(milliseconds: 0),
);
},
onUnknownRoute: (val) {
print(val);
},
observers: <NavigatorObserver>[]
),
),
Text('Navigator執行尋找路由順序'),
Text('initialRoute'),
Text('onGenerateRoute'),
Text('onUnknownRoute'),
],
),
);
}
}
第二個種,初始化執行路線,routes ->onUnknownRoute,路由跳轉Navigator.pushNamed(context, “secondPage”);,之后會到routes 路由集合之后,能匹配到正確的路由子路由,那么就跳轉到子路由中
例子:
import 'package:flutter/material.dart';
import 'package:flutter_routes/errorpage.dart';
import 'package:flutter_routes/homepage.dart';
import 'package:flutter_routes/navigator_with_result.dart';
import 'package:flutter_routes/page1.dart';
import 'package:flutter_routes/page2.dart';
import 'package:flutter_routes/page3.dart';
import 'package:flutter_routes/page4.dart';
import 'package:flutter_routes/page5.dart';
import 'package:flutter_routes/pageroutebuilderresult.dart';
import 'package:flutter_routes/splash.dart';
import 'package:flutter_routes/testpageroutebuilder.dart';
import 'package:flutter_routes/todo.dart';
import 'package:flutter_routes/welcome.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter路由',
theme: ThemeData(
primarySwatch: Colors.blue,
),
// 路由集合
routes: {
'/page1': (context) => Page1(),
'/page2': (context) => Page2(),
'/page3': (context) => Page3(),
'/page4': (context) => Page4(),
'/page5': (context) => Page5(),
'/todo': (context) => TodosScreen(),
'/splash': (context) => Splash(),
'/welcome': (context) => Welcome(),
'/homepage': (context) => HomePage(),
'/PageRouteBuilder': (context) => TestPageRouteBuilder(),
'/PageRouteBuilderResult': (context) => PageRouteBuilderResult(),
},
// 找不到路由,顯示的錯誤頁面
onUnknownRoute: (RouteSettings setting) {
String name = setting.name;
print("未匹配到路由:$name");
return new MaterialPageRoute(builder: (context) {
return new ErrorPage();
});
},
home: Page1(),
);
}
}
Page1 頁面
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
class Page1 extends StatelessWidget {
Page1({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('page1'),
),
body: Center(
child: RaisedButton(
child: Text('跳轉到Page2'),
onPressed: () {
// 路由跳轉
Navigator.pushNamed(context, '/page2');
},
),
),
);
}
}
在實際開發過程中,建議用命名路由方式來跳轉新的頁面,便於維護,開發項目
路由堆棧的使用方式
1、在用這種方式路由跳轉新頁面的時候,是把頁面放在堆棧里面,這個棧的特性就是,先進后出, Navigator.push 或者 pushNamed 實現的,每次都是把頁面壓入堆棧,在回退 的時候會回退到上一跳頁面
Navigator.of(context).pushNamed('/search');
1
2.如果需要清空堆棧,比如我需要直接返回首頁,之前的所有路由全部干掉,堆棧清空
Navigator.of(context).pushNamedAndRemoveUntil
1
頁面退出堆棧
Navigator.pop(context, "我是返回值"),
1
參考文章
https://blog.csdn.net/weixin_30512027/article/details/85334391
https://blog.csdn.net/weixin_34999505/article/details/86760606
————————————————
版權聲明:本文為CSDN博主「逐流間隔年」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/senkai123/java/article/details/102948524