Skip to main content

导航到新屏幕并返回

大多数应用程序包含多个屏幕来显示不同类型的信息。 例如,一个应用程序可能有一个显示产品的屏幕。 当用户点击产品图片时,会显示一个新屏幕来显示产品详细信息。

在 Android 中,路由相当于 Activity。 在 iOS 中,路由相当于 ViewController。 在 Flutter 中,路由只是一个 Widget。

本食谱使用 Navigator 来导航到新的路由。

接下来的几节将展示如何使用以下步骤在两个路由之间导航:

  1. 创建两个路由。
  2. 使用 Navigator.push() 导航到第二个路由。
  3. 使用 Navigator.pop() 返回第一个路由。

1. 创建两个路由

#

首先,创建两个要使用的路由。由于这是一个基本示例,每个路由只包含一个按钮。点击第一个路由上的按钮将导航到第二个路由。点击第二个路由上的按钮将返回第一个路由。

首先,设置可视化结构:

dart
class FirstRoute extends StatelessWidget {
  const FirstRoute({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('First Route'),
      ),
      body: Center(
        child: ElevatedButton(
          child: const Text('Open route'),
          onPressed: () {
            // 点击时导航到第二个路由。
          },
        ),
      ),
    );
  }
}

class SecondRoute extends StatelessWidget {
  const SecondRoute({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Second Route'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            // 点击时导航回第一个路由。
          },
          child: const Text('Go back!'),
        ),
      ),
    );
  }
}

2. 使用 Navigator.push() 导航到第二个路由

#

要切换到新的路由,请使用 Navigator.push() 方法。push() 方法将 Route 添加到由 Navigator 管理的路由堆栈中。Route 从哪里来?您可以创建自己的 Route,或者使用 MaterialPageRoute,这很有用,因为它使用特定于平台的动画过渡到新的路由。

FirstRoute Widget 的 build() 方法中,更新 onPressed() 回调:

dart
// 在 `FirstRoute` Widget 中:
onPressed: () {
  Navigator.push(
    context,
    MaterialPageRoute(builder: (context) => const SecondRoute()),
  );
}

3. 使用 Navigator.pop() 返回第一个路由

#

如何关闭第二个路由并返回到第一个路由?通过使用 Navigator.pop() 方法。pop() 方法从由 Navigator 管理的路由堆栈中删除当前 Route

要实现返回原始路由,请更新 SecondRoute Widget 中的 onPressed() 回调:

dart
// 在 SecondRoute Widget 中
onPressed: () {
  Navigator.pop(context);
}

交互式示例

#
import 'package:flutter/material.dart';

void main() {
  runApp(const MaterialApp(
    title: 'Navigation Basics',
    home: FirstRoute(),
  ));
}

class FirstRoute extends StatelessWidget {
  const FirstRoute({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('First Route'),
      ),
      body: Center(
        child: ElevatedButton(
          child: const Text('Open route'),
          onPressed: () {
            Navigator.push(
              context,
              MaterialPageRoute(builder: (context) => const SecondRoute()),
            );
          },
        ),
      ),
    );
  }
}

class SecondRoute extends StatelessWidget {
  const SecondRoute({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Second Route'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pop(context);
          },
          child: const Text('Go back!'),
        ),
      ),
    );
  }
}

使用 CupertinoPageRoute 进行导航

#

在前面的示例中,您学习了如何使用 Material 组件 中的 MaterialPageRoute 在屏幕之间导航。但是,在 Flutter 中,您不仅限于 Material 设计语言,还可以访问 Cupertino(iOS 风格)Widget。

使用 Cupertino Widget 进行导航的步骤与使用 MaterialPageRoute 时相同,但是您使用的是 CupertinoPageRoute,它提供 iOS 风格的过渡动画。

在下面的示例中,这些 Widget 已被替换:

这样,示例遵循当前的 iOS 设计语言。

import 'package:flutter/cupertino.dart';

void main() {
  runApp(const CupertinoApp(
    title: 'Navigation Basics',
    home: FirstRoute(),
  ));
}

class FirstRoute extends StatelessWidget {
  const FirstRoute({super.key});

  @override
  Widget build(BuildContext context) {
    return CupertinoPageScaffold(
      navigationBar: const CupertinoNavigationBar(
        middle: Text('First Route'),
      ),
      child: Center(
        child: CupertinoButton(
          child: const Text('Open route'),
          onPressed: () {
            Navigator.push(
              context,
              CupertinoPageRoute(builder: (context) => const SecondRoute()),
            );
          },
        ),
      ),
    );
  }
}

class SecondRoute extends StatelessWidget {
  const SecondRoute({super.key});

  @override
  Widget build(BuildContext context) {
    return CupertinoPageScaffold(
      navigationBar: const CupertinoNavigationBar(
        middle: Text('Second Route'),
      ),
      child: Center(
        child: CupertinoButton(
          onPressed: () {
            Navigator.pop(context);
          },
          child: const Text('Go back!'),
        ),
      ),
    );
  }
}