跳至主要内容

导航和路由

Flutter 提供了一个完整的系统,用于在屏幕之间导航和处理深层链接。小型应用程序如果没有复杂的深层链接需求,可以使用 Navigator,而具有特定深层链接和导航需求的应用程序也应该使用 Router 来正确处理 Android 和 iOS 上的深层链接,并在应用程序在 Web 上运行时与地址栏保持同步。

要配置您的 Android 或 iOS 应用程序以处理深层链接,请参阅 深层链接

使用 Navigator

#

Navigator 小部件使用目标平台的正确过渡动画将屏幕显示为堆栈。要导航到新屏幕,请通过路由的 BuildContext 访问 Navigator 并调用诸如 push()pop() 之类的命令式方法。

dart
onPressed: () {
  Navigator.of(context).push(
    MaterialPageRoute(
      builder: (context) => const SongScreen(song: song),
    ),
  );
},
child: Text(song.name),

因为 Navigator 保留了一个 Route 对象(表示历史堆栈)的堆栈,所以 push() 方法也接受一个 Route 对象。MaterialPageRoute 对象是 Route 的一个子类,它指定了 Material Design 的过渡动画。有关如何使用 Navigator 的更多示例,请遵循 Flutter 菜谱中的 导航菜谱 或访问 Navigator API 文档

使用命名路由

#

具有简单导航和深层链接需求的应用程序可以使用 Navigator 进行导航,并使用 MaterialApp.routes 参数进行深层链接。

dart
@override
Widget build(BuildContext context) {
  return MaterialApp(
    routes: {
      '/': (context) => HomeScreen(),
      '/details': (context) => DetailScreen(),
    },
  );
}

此处指定的路由称为命名路由。有关完整示例,请遵循 Flutter 菜谱中的 使用命名路由导航 菜谱。

限制

#

尽管命名路由可以处理深层链接,但行为始终相同,并且无法自定义。当平台接收到新的深层链接时,Flutter 会将新的 Route 推送到 Navigator,无论用户当前位于何处。

Flutter 也不支持使用命名路由的应用程序的浏览器前进按钮。由于这些原因,我们不建议在大多数应用程序中使用命名路由。

使用 Router

#

具有高级导航和路由需求的 Flutter 应用程序(例如使用指向每个屏幕的直接链接的 Web 应用程序,或具有多个 Navigator 小部件的应用程序)应该使用路由包(例如 go_router),该包可以解析路由路径并在应用程序接收到新的深层链接时配置 Navigator

要使用 Router,请切换到 MaterialAppCupertinoApp 上的 router 构造函数,并为其提供 Router 配置。路由包(例如 go_router)通常会为您提供配置。例如

dart
MaterialApp.router(
  routerConfig: GoRouter(
    // …
  )
);

因为像 go_router 这样的包是声明式的,所以当接收到深层链接时,它们将始终显示相同的屏幕。

同时使用 Router 和 Navigator

#

RouterNavigator 旨在协同工作。您可以通过声明式路由包(例如 go_router)或通过在 Navigator 上调用诸如 push()pop() 之类的命令式方法来使用 Router API 进行导航。

当您使用 Router 或声明式路由包进行导航时,Navigator 上的每个路由都是页面支持的,这意味着它是使用 Pagepages 参数在 Navigator 构造函数上创建的。相反,通过调用 Navigator.pushshowDialog 创建的任何 Route 都会向 Navigator 添加一个无页面路由。如果您正在使用路由包,则页面支持的路由始终是可深层链接的,而无页面路由则不是。

页面支持RouteNavigator 中移除时,其后的所有无页面路由也会被移除。例如,如果深层链接通过从 Navigator 中移除页面支持的路由来导航,则其后的所有无页面路由(直到下一个页面支持的路由)也会被移除。

Web 支持

#

使用 Router 类的应用程序与浏览器历史记录 API 集成,以便在使用浏览器的后退和前进按钮时提供一致的体验。每当您使用 Router 进行导航时,都会将历史记录 API 条目添加到浏览器的历史记录堆栈中。按下后退按钮使用反向时间顺序导航,这意味着用户将被带到之前使用 Router 显示的位置。这意味着如果用户从 Navigator 中弹出页面,然后按下浏览器的后退按钮,则前一个页面将被推回堆栈。

更多信息

#

有关导航和路由的更多信息,请查看以下资源

  • Flutter 菜谱包含多个 导航菜谱,展示了如何使用 Navigator
  • NavigatorRouter API 文档包含有关如何在没有路由包的情况下设置声明式导航的详细信息。
  • 了解导航,Material Design 文档中的一个页面,概述了设计应用程序导航的概念,包括对向前、向上和时间顺序导航的解释。
  • 学习 Flutter 的新导航和路由系统,Medium 上的一篇文章,描述了如何在没有路由包的情况下直接使用 Router 小部件。
  • Router 设计文档 包含 Router API 的动机和设计。