什么是路由?
对于移动开发者来说,路由指的就是页面,在 Android 中就是 activity,在 ios 中Wie ViewController 说简单点就是映射页面跳转关系的,当然它也包含跳转相关的一切功能 而路由管理则就是管理这些页面直接跳转,通信方式等
示例
1,创建一个新的路由,命名 NewRoute
代码语言:javascript复制/// StatelessWidget 无状态组件
class NewRoute extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("FlutterStudy"),
),
body: Center(
child: Text(
"This is new route",
style: Theme.of(context).textTheme.headline3,
),
),
);
}
}
复制代码
2,创建一个文本按钮,点击进行跳转
代码语言:javascript复制FlatButton(
child: Text("点击跳转"),
textColor: Colors.red,
onPressed: () {
//导航到新的路由
Navigator.push(context, MaterialPageRoute(builder: (context) {
return NewRoute();
}));
},
)
复制代码
效果:
MaterialPageRoute
MaterialPageRoute 是 Material 组件库提供的组件,他可以针对不同的平台,实现与平台页面切换动画风格一致切换动画
MaterialPageRoute 继承自 PageRoute 类,PageRoute 是一个抽象类,表示整个屏幕空间的一个模态路由页面,其中定义了路由构建及切换时过度动画的相关接口和属性;如果想自定义路由切换动画,可自己继承 PageRoute 来实现
- 构造方法
MaterialPageRoute({
required this.builder,
RouteSettings? settings,
this.maintainState = true,
bool fullscreenDialog = false,
})
Navigator
Navigator 是一个路由管理组件,它提供了打开和退出路由方法
Navigator 通过栈来管理活动路由集合,通常屏幕显示的页面就是栈顶路由
打开一个页面
代码语言:javascript复制 static Future<T?> push<T extends Object?>(BuildContext context, Route<T> route) {
return Navigator.of(context)!.push(route);
}
复制代码
将给定的路由入栈(打开页面),返回 future 对象,用于接收该路由出栈是返回的数据。
关闭一个页面
代码语言:javascript复制static void pop<T extends Object?>(BuildContext context, [ T? result ]) {
Navigator.of(context)!.pop<T>(result);
}
复制代码
将栈顶路由出栈,reslut 为要返回给上一个页面的数据
路由传值
代码语言:javascript复制class TipRoute extends StatelessWidget {
TipRoute({Key key, this.text}) : super(key: key);
final String text;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("提示"),
),
body: Padding(
padding: EdgeInsets.all(18),
child: Center(
child: Column(
children: <Widget>[
Text(text),
RaisedButton(
onPressed: () => Navigator.pop(context, "我是返回值"),
child: Text("返回"),
)
],
),
)),
);
}
}
复制代码
代码很简单,在界面中添加了一个 appbar,在中间显示一个文本,和一个 RaisedButton,并且点击进行 pop 并传入要返回的值
代码语言:javascript复制class RouterTestRoute extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: RaisedButton(
onPressed: () async {
await Navigator.push(context, MaterialPageRoute(builder: (context) {
return TipRoute(text: "我是参数");
})).then((value) => print("路由返回值 $value"));
},
child: Text("打开提示页面"),
),
);
}
}
复制代码
在 onPressed 方法中,异步执行这个函数,最终将返回值打印出来
如果不了解 async 可查看这篇文章,Dart,随用随查
运行上面的代码,点击 "打开提示页面",效果如下所示
打印的结果
代码语言:javascript复制I/flutter (23778): 路由返回值 我是返回值
复制代码
需要注意的是
1,参数是通过构造方法传入的
2,如果点击左上角,或者返回按钮进行返回,则页面返回的值为 null
命名路由
有名字的路由,给路由起一个名字,就可以通过名字直接打开路由了
路由表
路由表就是一个 map,key 为路由名字,value 是一个 builder 的回调函数,用于生成相应的路由 widget。如下:
代码语言:javascript复制final Map<String, WidgetBuilder>? routes;
复制代码
注册路由
在 MaterialApp 里面,添加 routes 属性即可,如下:
代码语言:javascript复制Widget build(BuildContext context) {
return MaterialApp(
//app name
title: 'FlutterStudy',
theme: ThemeData(
primarySwatch: Colors.red,
),
routes: {
"new_page": (context) => NewRoute(),
"/": (context) => MyHomePage(title: "Flutter Study")
},
//应用首页路由
home: MyHomePage(title: 'Flutter Study'),
);
}
复制代码
打开路由页面
代码语言:javascript复制TextButton(
child: Text("自定义 Button"),
onPressed: () {
Navigator.pushNamed(context, "router_test");
})
复制代码
在点击的事件中,跳转到对于的路由页面
带参数的命名路由传递
代码语言:javascript复制routes: {
"new_page": (context) => NewRoute(),
},
复制代码
在路由表里面注册
代码语言:javascript复制class NewRoute extends StatelessWidget {
@override
Widget build(BuildContext context) {
var args = ModalRoute.of(context).settings.arguments;
//.......
}
复制代码
接受参数
代码语言:javascript复制Navigator.pushNamed(context, "new_page",arguments: "Hello World");
复制代码
在跳转的时候发送数据即可
路由生成钩子
在打开某些页面的时候可能需要做一些权限检测,如用户是否登录,是否需要密码等,如果每次打开路由的时候都要去判断一下会非常麻烦,这种情况可以通过 MaterialApp 实现
MaterialApp 有一个 onGenerateRoute 属性,他在打开路由时可能会被调用,之所以说可能,是应为当调用 Navigator.pushNamed() 打开路由时,如果指定的路由在路由表中已经注册,则会调用路由表中的 builder 函数来生成路由组件;如果路由表中没有注册,才会调用 onGenerateRoute 来生成路由。
代码语言:javascript复制MaterialApp(
... //省略无关代码
onGenerateRoute:(RouteSettings settings){
return MaterialPageRoute(builder: (context){
String routeName = settings.name;
// 如果访问的路由页需要登录,但当前未登录,则直接返回登录页路由,
// 引导用户登录;其它情况则正常打开路由。
}
);
}
);
复制代码
参考资料:
Flutter官网 Flutter 实战