1 Flutter 中的路由
Flutter 中的路由通俗的讲就是页面跳转。在 Flutter 中通过 Navigator 组件管理路由导航。 并提供了管理堆栈的方法。如:Navigator.push 和 Navigator.pop
Flutter 中给我们提供了两种配置路由跳转的方式:1、基本路由 2、命名路由
2 基本路由
通过 Navigator 的 push 和 pop 方法实现路由的跳转和返回。通过构造函数传参,实现路由之间的参数传递。
import 'package:flutter/material.dart';
import './Detail.dart';
class HomePage extends StatefulWidget {
HomePage({Key key}) : super(key: key);
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
SizedBox(height: 100),
RaisedButton(
child: Text('go to Detail'),
textColor: Theme.of(context).accentColor,
textTheme: ButtonTextTheme.primary,
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Detail(title: '我是从home进入的参数'),
),
);
},
),
],
),
);
}
}
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Detail(title: '我是从home进入的参数'),
),
);
- Detail.dart 详情页,新的组件外层需要返回 Scaffold 组件。
import 'package:flutter/material.dart';
class Detail extends StatefulWidget {
final String title;
Detail({Key key, this.title}) : super(key: key);
@override
_DetailState createState() => _DetailState(this.title);
}
class _DetailState extends State<Detail> {
final String title;
_DetailState(this.title);
@override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton( // 实现浮动返回按钮
child: Text('返回'),
onPressed: () {
// Navigator.pop(context);
Navigator.of(context).pop();
},
),
appBar: AppBar(
title: Text(this.title ?? '详情'),
),
body: Container(
child: Column(
children: <Widget>[
Text('xxxxx'),
SizedBox(height: 30),
],
),
),
);
}
}

3 命名式路由
在 MaterialApp 中配置统一路由。
- 命名式路由传参,方式一
main.dart
import 'package:flutter/material.dart';
import 'tabs/Tabs.dart';
import 'package:app03/pages/home/Detail.dart';
import 'res/listData.dart';
void main() {
runApp(new MyApp());
}
// 自定义组件
class MyApp extends StatelessWidget {
// 1 配置统一命名路由
final routes = {
'/detail': (context) => Detail(
routesArgs:
ModalRoute.of(context).settings.arguments), // 2 根据组件构造函数参数,传递路由参数
};
@override
Widget build(BuildContext context) {
// TODO: implement build
return MaterialApp(
routes: routes,
// Scaffold 定义导航头部和页面主要内容
home: TabsPage(),
theme: ThemeData(
primarySwatch: Colors.green,
),
);
}
}
HomePage.dart
import 'package:flutter/material.dart';
import './Detail.dart';
class HomePage extends StatefulWidget {
HomePage({Key key}) : super(key: key);
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
SizedBox(height: 100),
RaisedButton(
child: Text('go to Detail'),
textColor: Theme.of(context).accentColor,
textTheme: ButtonTextTheme.primary,
onPressed: () {
Navigator.of(context).pushNamed(
"/detail",
arguments: {"id": 123}, // 3 使用 arguments 传值,注意类型
);
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => Detail(title: '我是从home进入的参数'),
// ),
// );
},
),
],
),
);
}
}
Detail.dart
import 'package:flutter/material.dart';
class Detail extends StatefulWidget {
final String title;
// 4 定义对应的构造参数,注意类型要对应
final Map routesArgs;
Detail({Key key, this.title, this.routesArgs}) : super(key: key);
@override
_DetailState createState() => _DetailState();
}
class _DetailState extends State<Detail> {
@override
Widget build(BuildContext context) {
// 5 组件内,获取路由参数
var args = ModalRoute.of(context).settings.arguments;
var _args = args as Map; // 如果参数不是为 String 类型,例如 Map 类型等其他类型,需要做强制转换
print(_args['id']);
return Scaffold(
floatingActionButton: FloatingActionButton(
child: Text('返回'),
onPressed: () {
// Navigator.pop(context);
Navigator.of(context).pop();
},
),
appBar: AppBar(
title: Text("详情${_args['id']}"),
// title: Text("详情${(args as Map)['id']}"),
),
body: Container(
child: Column(
children: <Widget>[
Text('xxxxx'),
SizedBox(height: 30),
],
),
),
);
}
}
- 命名式路由传参,方式二
main.dart
import 'package:flutter/material.dart';
import 'tabs/Tabs.dart';
import 'package:app03/pages/home/Detail.dart';
import 'package:app03/pages/home/FormPage.dart';
import 'res/listData.dart';
void main() {
runApp(new MyApp());
}
// 自定义组件
class MyApp extends StatelessWidget {
// 1 配置统一命名路由
final routes = {
'/detail': (context) => Detail(), // 2 根据组件构造函数参数,传递路由参数
'/form': (context, {arguments}) => FormPage(arguments: arguments),
};
@override
Widget build(BuildContext context) {
// TODO: implement build
return MaterialApp(
// routes: routes, // 注意:方式二不用配置,方式一才需要,不然会有问题!!!
// Scaffold 定义导航头部和页面主要内容
home: TabsPage(),
onGenerateRoute: (RouteSettings settings) {
print('-------${settings.arguments}');
// 统一处理
final String name = settings.name;
final Function pageContentBuilder = this.routes[name];
if (pageContentBuilder != null) {
if (settings.arguments != null) {
final Route route = MaterialPageRoute(
builder: (context) =>
pageContentBuilder(context, arguments: settings.arguments));
return route;
} else {
final Route route = MaterialPageRoute(
builder: (context) => pageContentBuilder(context));
return route;
}
}
},
theme: ThemeData(
primarySwatch: Colors.green,
),
);
}
}
HomePage.dart
import 'package:flutter/material.dart';
import './Detail.dart';
class HomePage extends StatefulWidget {
HomePage({Key key}) : super(key: key);
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
SizedBox(height: 100),
RaisedButton(
child: Text('go to Detail'),
textColor: Theme.of(context).accentColor,
textTheme: ButtonTextTheme.primary,
onPressed: () {
Navigator.of(context)
.pushNamed("/detail"); // 如果不需要参数就不要写,不然有问题!!!
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => Detail(title: '我是从home进入的参数'),
// ),
// );
},
),
SizedBox(height: 40),
RaisedButton(
child: Text('go to Form'),
textColor: Theme.of(context).accentColor,
textTheme: ButtonTextTheme.primary,
onPressed: () {
Navigator.pushNamed(context, '/form', arguments: {"id": 20});
// Navigator.of(context).pushNamed(
// "/form",
// arguments: {"id": 4445}, // 3 使用 arguments 传值,注意类型
// );
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => Detail(title: '我是从home进入的参数'),
// ),
// );
},
),
],
),
);
}
}
FormPage.dart
import 'package:flutter/material.dart';
class FormPage extends StatefulWidget {
final Map arguments;
// FormPage({this.arguments});
FormPage({Key key, this.arguments}) : super(key: key);
// print(arguments);
@override
_FormPageState createState() => _FormPageState(arguments: this.arguments);
}
class _FormPageState extends State<FormPage> {
final Map arguments;
_FormPageState({this.arguments});
@override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
child: Text('返回'),
onPressed: () {
// Navigator.pop(context);
Navigator.of(context).pop();
},
),
appBar: AppBar(
title: Text("Form 表单"),
// title: Text("详情${(args as Map)['id']}"),
),
body: Container(
child: Column(
children: <Widget>[
Text("我是一个表单页面 ${arguments != null ? arguments['id'] : '0'}"),
SizedBox(height: 30),
],
),
),
);
}
}
// import 'package:flutter/material.dart';
// class FormPage extends StatelessWidget {
// final Map arguments;
// FormPage({this.arguments});
// @override
// Widget build(BuildContext context) {
// // print(arguments);
// return Scaffold(
// appBar: AppBar(
// title: Text("搜索"),
// ),
// body: Text("我是一个表单页面 ${arguments != null ? arguments['id'] : '0'}"));
// }
// }
Detail.dart
import 'package:flutter/material.dart';
class Detail extends StatefulWidget {
final String title;
// 4 定义对应的构造参数,注意类型要对应
final Map routesArgs;
Detail({Key key, this.title, this.routesArgs}) : super(key: key);
@override
_DetailState createState() => _DetailState();
}
class _DetailState extends State<Detail> {
@override
Widget build(BuildContext context) {
// 5 组件内,获取路由参数
// var args = ModalRoute.of(context).settings.arguments;
// var _args = args as Map; // 如果参数不是为 String 类型,例如 Map 类型等其他类型,需要做强制转换
// print(_args['id']);
return Scaffold(
floatingActionButton: FloatingActionButton(
child: Text('返回'),
onPressed: () {
// Navigator.pop(context);
Navigator.of(context).pop();
},
),
appBar: AppBar(
title: Text("详情"),
// title: Text("详情${_args['id']}"),
// title: Text("详情${(args as Map)['id']}"),
),
body: Container(
child: Column(
children: <Widget>[
Text('xxxxx'),
SizedBox(height: 30),
],
),
),
);
}
}
4 抽离命名路由为单独文件
main.dart
import 'package:flutter/material.dart';
// import 'tabs/Tabs.dart';
import 'package:app03/routers/Routers.dart';
import 'res/listData.dart';
void main() {
runApp(new MyApp());
}
// 自定义组件
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return MaterialApp(
// Scaffold 定义导航头部和页面主要内容
// home: TabsPage(),
initialRoute: '/', // 抽离 tabs 到路由,需要配置 initialRoute
onGenerateRoute: onGenerateRoute,
theme: ThemeData(
primarySwatch: Colors.green,
),
);
}
}
Routers.dart
import 'package:flutter/material.dart';
import 'package:app03/tabs/Tabs.dart';
import 'package:app03/pages/home/Detail.dart';
import 'package:app03/pages/home/FormPage.dart';
final Map<String, Function> routes = {
'/': (context) => TabsPage(),
'/detail': (context) => Detail(), // 2 根据组件构造函数参数,传递路由参数
'/form': (context, {arguments}) => FormPage(arguments: arguments),
};
var onGenerateRoute = (RouteSettings settings) {
print('-------${settings.arguments}');
// 统一处理
final String name = settings.name;
final Function pageContentBuilder = routes[name];
if (pageContentBuilder != null) {
if (settings.arguments != null) {
final Route route = MaterialPageRoute(
builder: (context) =>
pageContentBuilder(context, arguments: settings.arguments));
return route;
} else {
final Route route =
MaterialPageRoute(builder: (context) => pageContentBuilder(context));
return route;
}
}
};
Tabs.dart(Tabs 组件不变,还是原来的代码)
import 'package:flutter/material.dart';
import 'package:app03/pages/home/HomePage.dart';
import 'package:app03/pages/category/CategoryPage.dart';
import 'package:app03/pages/settings/SettingsPage.dart';
class TabsPage extends StatefulWidget {
TabsPage({Key key}) : super(key: key);
@override
_TabsPageState createState() => _TabsPageState();
}
class _TabsPageState extends State<TabsPage> {
int currentIndex = 0;
List listTabs = [
HomePage(),
CategoryPage(),
SettingsPage(),
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('flutter 标题'),
),
body: this.listTabs[this.currentIndex],
bottomNavigationBar: BottomNavigationBar(
currentIndex: this.currentIndex,
iconSize: 30.0,
type: BottomNavigationBarType.fixed,
onTap: (index) {
setState(() {
this.currentIndex = index;
});
},
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
title: Text('首页'),
),
BottomNavigationBarItem(
icon: Icon(Icons.category),
title: Text('分类'),
),
BottomNavigationBarItem(
icon: Icon(Icons.settings),
title: Text('设置'),
),
],
),
);
}
}

5 替换路由和根路由
CategoryPage.dart (tab 页面进入新的 register 页面)
import 'package:flutter/material.dart';
class CategoryPage extends StatefulWidget {
CategoryPage({Key key}) : super(key: key);
@override
_CategoryPageState createState() => _CategoryPageState();
}
class _CategoryPageState extends State<CategoryPage> {
@override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
Text('Category...'),
SizedBox(
height: 30,
),
RaisedButton(
child: Text('go to 注册'),
onPressed: () {
Navigator.pushNamed(context, '/registerFirst');
},
)
],
),
);
}
}
RegisterFirst.dart
import 'package:flutter/material.dart';
class RegisterFirstPage extends StatefulWidget {
RegisterFirstPage({Key key}) : super(key: key);
@override
_RegisterFirstPageState createState() => _RegisterFirstPageState();
}
class _RegisterFirstPageState extends State<RegisterFirstPage> {
@override
Widget build(BuildContext context) {
return Container(
child: Scaffold(
appBar: AppBar(
title: Text('注册'),
),
body: Column(
children: <Widget>[
SizedBox(height: 100, width: 50),
Text('注册步骤一'),
RaisedButton(
child: Text('下一步'),
onPressed: () {
Navigator.of(context).pushNamed("/registerSecond"); // 普通方式跳转
// Navigator.of(context).pushReplacementNamed(
// "/registerSecond"); // 替换路由,Second 路由会替换该 First 路由,所以 Second 返回上一步,就是返回之前 First 路由的上一步。
},
)
],
),
),
);
}
}
RegisterSecond.dart(替换路由跳转)
import 'package:flutter/material.dart';
class RegisterSecondPage extends StatefulWidget {
RegisterSecondPage({Key key}) : super(key: key);
@override
_RegisterSecondPageState createState() => _RegisterSecondPageState();
}
class _RegisterSecondPageState extends State<RegisterSecondPage> {
@override
Widget build(BuildContext context) {
return Container(
child: Scaffold(
appBar: AppBar(
title: Text('注册'),
),
body: Column(
children: <Widget>[
SizedBox(height: 100, width: 50),
Text('注册步骤二'),
RaisedButton(
child: Text('下一步'),
onPressed: () {
Navigator.of(context).pushNamed("/registerThree");
},
)
],
),
),
);
}
}
RegisterThree.dart(根路由跳转)
import 'package:flutter/material.dart';
import 'package:app03/tabs/Tabs.dart';
class RegisterThreePage extends StatefulWidget {
RegisterThreePage({Key key}) : super(key: key);
@override
_RegisterThreePageState createState() => _RegisterThreePageState();
}
class _RegisterThreePageState extends State<RegisterThreePage> {
@override
Widget build(BuildContext context) {
return Container(
child: Scaffold(
appBar: AppBar(
title: Text('注册'),
),
body: Column(
children: <Widget>[
SizedBox(height: 100, width: 50),
Text('注册步骤三'),
RaisedButton(
child: Text('确定'),
onPressed: () {
Navigator.of(context).pushAndRemoveUntil(
// 返回到指定到根路由
new MaterialPageRoute(builder: (context) => new TabsPage()),
(route) => route == null);
},
)
],
),
),
);
}
}
- 扩展上面的例子,新增传递 Tabs 参数
RegisterThree.dart
import 'package:flutter/material.dart';
import 'package:app03/tabs/Tabs.dart';
class RegisterThreePage extends StatefulWidget {
RegisterThreePage({Key key}) : super(key: key);
@override
_RegisterThreePageState createState() => _RegisterThreePageState();
}
class _RegisterThreePageState extends State<RegisterThreePage> {
@override
Widget build(BuildContext context) {
return Container(
child: Scaffold(
appBar: AppBar(
title: Text('注册'),
),
body: Column(
children: <Widget>[
SizedBox(height: 100, width: 50),
Text('注册步骤三'),
RaisedButton(
child: Text('确定'),
onPressed: () {
Navigator.of(context).pushAndRemoveUntil(
// 返回到指定到根路由
new MaterialPageRoute(
builder: (context) => new TabsPage(index: 1)), // !!!
(route) => route == null);
},
)
],
),
),
);
}
}
Tabs.dart
import 'package:flutter/material.dart';
import 'package:app03/pages/home/HomePage.dart';
import 'package:app03/pages/category/CategoryPage.dart';
import 'package:app03/pages/settings/SettingsPage.dart';
class TabsPage extends StatefulWidget {
final int index;
TabsPage({Key key, this.index = 0}) : super(key: key);
@override
_TabsPageState createState() => _TabsPageState(this.index);
}
class _TabsPageState extends State<TabsPage> {
int currentIndex = 0;
_TabsPageState(index) {
this.currentIndex = index;
}
List listTabs = [
HomePage(),
CategoryPage(),
SettingsPage(),
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('flutter 标题'),
),
body: this.listTabs[this.currentIndex],
bottomNavigationBar: BottomNavigationBar(
currentIndex: this.currentIndex,
iconSize: 30.0,
type: BottomNavigationBarType.fixed,
onTap: (index) {
setState(() {
this.currentIndex = index;
});
},
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
title: Text('首页'),
),
BottomNavigationBarItem(
icon: Icon(Icons.category),
title: Text('分类'),
),
BottomNavigationBarItem(
icon: Icon(Icons.settings),
title: Text('设置'),
),
],
),
);
}
}
网友评论