携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第9天,点击查看活动详情
我们在Navigator 1.0 的时候使用 Flutter,你可能会使用Navigator并且熟悉以下概念:
Navigator— 管理一堆 Route 对象的小部件。Route— 由 一个表示Navigator的屏幕的对象管理,通常由MaterialPageRoute.
在 Navigator 2.0 之前,使用命名路由或匿名路由Routes将其推送和弹出到Navigator' 堆栈。接下来的部分是对这两种方法的简要回顾。
匿名路由
大多数移动应用程序会在彼此的顶部显示屏幕,就像堆栈一样。在 Flutter 中,这很容易通过使用Navigator.
MaterialApp并且CupertinoApp已经Navigator在引擎盖下使用了。您可以使用 访问导航器Navigator.of()或使用显示新屏幕Navigator.push(),然后使用以下命令返回上一个屏幕Navigator.pop():
import 'package:flutter/material.dart';
void main() {
runApp(Nav2App());
}
class Nav2App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Center(
child: FlatButton(
child: Text('View Details'),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return DetailScreen();
}),
);
},
),
),
);
}
}
class DetailScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Center(
child: FlatButton(
child: Text('Pop!'),
onPressed: () {
Navigator.pop(context);
},
),
),
);
}
}
当push()被调用时,DetailScreen小部件被放置在小部件的顶部。前一个屏幕 HomeScreen仍然是小部件树的一部分,因此State与其关联的任何对象都会在DetailScreen可见时保留。
命名路线
Flutter 还支持命名路由,它们在routes参数 onMaterialApp或中定义CupertinoApp:
import 'package:flutter/material.dart';
void main() {
runApp(Nav2App());
}
class Nav2App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
routes: {
'/': (context) => HomeScreen(),
'/details': (context) => DetailScreen(),
},
);
}
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Center(
child: FlatButton(
child: Text('View Details'),
onPressed: () {
Navigator.pushNamed(
context,
'/details',
);
},
),
),
);
}
}
class DetailScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Center(
child: FlatButton(
child: Text('Pop!'),
onPressed: () {
Navigator.pop(context);
},
),
),
);
}
}
这些路由必须是预定义的。尽管您可以将参数传递给命名路由,但您无法解析路由本身的参数。例如,如果应用程序在 Web 上运行,则无法解析来自/details/:id。
使用 onGenerateRoute 的高级命名路由
处理命名路由的一种更灵活的方法是使用onGenerateRoute. 此 API 使您能够处理所有路径:
onGenerateRoute: (settings) {
// Handle '/'
if (settings.name == '/') {
return MaterialPageRoute(builder: (context) => HomeScreen());
}
// Handle '/details/:id'
var uri = Uri.parse(settings.name);
if (uri.pathSegments.length == 2 &&
uri.pathSegments.first == 'details') {
var id = uri.pathSegments[1];
return MaterialPageRoute(builder: (context) => DetailScreen(id: id));
}
return MaterialPageRoute(builder: (context) => UnknownScreen());
},
这里,settings是 的一个实例RouteSettings。name 和 arguments 字段Navigator.pushNamed是调用时提供的值,或者initialRoute设置为什么。