导航到一个新页面和返回一节中,我们通过创建一个新的路由并将它推到 Navigator 类中学习到了如何导航到新的一个界面 (screen)。

然而,如果我们需要在应用的很多地方导航到同一界面,这样做就会导致代码重复。在这种情况下,定义“命名路由(named route)”并使用它进行导航就会非常方便。

要使用命名路由,我们可以使用 Navigator.pushNamed 方法。下面的例子展示如何使用“命名路由”来实现前一节中的功能。

步骤

  • 创建两个界面

  • 定义路由

  • 使用 Navigator.pushNamed 跳转到第二个界面

  • 使用 Navigator.pop 返回到第一个界面

1. 创建两个界面

首先,我们需要两个界面来开始。第一个界面将包含一个跳转到第二个界面的按钮。第二个界面将包含一个跳转回第一个界面的按钮。

  1. class FirstScreen extends StatelessWidget {
  2. @override
  3. Widget build(BuildContext context) {
  4. return Scaffold(
  5. appBar: AppBar(
  6. title: Text('First Screen'),
  7. ),
  8. body: Center(
  9. child: RaisedButton(
  10. child: Text('Launch screen'),
  11. onPressed: () {
  12. // 点击时跳转到第二个界面!(Navigate to second screen when tapped!)
  13. },
  14. ),
  15. ),
  16. );
  17. }
  18. }
  19. class SecondScreen extends StatelessWidget {
  20. @override
  21. Widget build(BuildContext context) {
  22. return Scaffold(
  23. appBar: AppBar(
  24. title: Text("Second Screen"),
  25. ),
  26. body: Center(
  27. child: RaisedButton(
  28. onPressed: () {
  29. // 点击时跳转回第一个界面!(Navigate back to first screen when tapped!)
  30. },
  31. child: Text('Go back!'),
  32. ),
  33. ),
  34. );
  35. }
  36. }

2. 定义路由

接下来,我们需要通过为 MaterialApp 的构造函数额外的属性:initialRouteroutes 自身,来定义我们的路由。

initialRoute 属性定义了应用应该从哪个路由启动。routes 属性定义了所有可用的命名路由,以及当我们跳转到这些路由时应该构建的 Widgets。

  1. MaterialApp(
  2. // 使用“/”命名路由来启动应用(Start the app with the "/" named route. In our case, the app will start)
  3. // 在这里,应用将从 FirstScreen Widget 启动(on the FirstScreen Widget)
  4. initialRoute: '/',
  5. routes: {
  6. // 当我们跳转到“/”时,构建 FirstScreen Widget(When we navigate to the "/" route, build the FirstScreen Widget)
  7. '/': (context) => FirstScreen(),
  8. // 当我们跳转到“/second”时,构建 SecondScreen Widget(When we navigate to the "/second" route, build the SecondScreen Widget)
  9. '/second': (context) => SecondScreen(),
  10. },
  11. );

注意:当使用 initialRoute 时,需要确保你没有同时定义 home 属性。

3. 跳转到第二个界面

准备好了 Widgets 和路由,我们就可以开始进行页面跳转!在这里,我们将使用 Navigator.pushNamed 函数。它会告诉 Flutter 去构建我们在 routes 表中定义的 Widget 并启动该界面。

FirstScreen Widget 的 build 方法中,我们将更新 onPressed 回调:

  1. // 在 `FirstScreen` Widget中(Within the `FirstScreen` Widget)
  2. onPressed: () {
  3. // 使用命名路由跳转到第二个界面(Navigate to the second screen using a named route)
  4. Navigator.pushNamed(context, '/second');
  5. }

4. 返回到第一个界面

为了能够跳转回第一个页面,我们可以使用 Navigator.pop 方法。

  1. // 在 SecondScreen Widget 中(Within the SecondScreen Widget)
  2. onPressed: () {
  3. // 通过从堆栈弹出当前路由(Navigate back to the first screen by popping the current route)
  4. // 来返回到第一个界面(off the stack)
  5. Navigator.pop(context);
  6. }

完整示例

  1. import 'package:flutter/material.dart';
  2. void main() {
  3. runApp(MaterialApp(
  4. title: 'Named Routes Demo',
  5. // 使用“/”命名路由来启动应用(Start the app with the "/" named route. In our case, the app will start)
  6. // 在这里,应用将从 FirstScreen Widget 启动(on the FirstScreen Widget)
  7. initialRoute: '/',
  8. routes: {
  9. // 当我们跳转到“/”时,构建 FirstScreen Widget(When we navigate to the "/" route, build the FirstScreen Widget)
  10. '/': (context) => FirstScreen(),
  11. // 当我们跳转到“/second”时,构建 SecondScreen Widget(When we navigate to the "/second" route, build the SecondScreen Widget)
  12. '/second': (context) => SecondScreen(),
  13. },
  14. ));
  15. }
  16. class FirstScreen extends StatelessWidget {
  17. @override
  18. Widget build(BuildContext context) {
  19. return Scaffold(
  20. appBar: AppBar(
  21. title: Text('First Screen'),
  22. ),
  23. body: Center(
  24. child: RaisedButton(
  25. child: Text('Launch screen'),
  26. onPressed: () {
  27. // 使用命名路由跳转到第二个界面(Navigate to the second screen using a named route)
  28. Navigator.pushNamed(context, '/second');
  29. },
  30. ),
  31. ),
  32. );
  33. }
  34. }
  35. class SecondScreen extends StatelessWidget {
  36. @override
  37. Widget build(BuildContext context) {
  38. return Scaffold(
  39. appBar: AppBar(
  40. title: Text("Second Screen"),
  41. ),
  42. body: Center(
  43. child: RaisedButton(
  44. onPressed: () {
  45. // 通过从堆栈弹出当前路由(Navigate back to the first screen by popping the current route)
  46. // 来返回到第一个界面(off the stack)
  47. Navigator.pop(context);
  48. },
  49. child: Text('Go back!'),
  50. ),
  51. ),
  52. );
  53. }
  54. }

Navigation Basics Demo