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

在 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: () {
            // Navigate to second route when tapped.
          },
        ),
      ),
    );
  }
}

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: () {
            // Navigate back to first route when tapped.
          },
          child: const Text('Go back!'),
        ),
      ),
    );
  }
}
dart
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: () {
            // Navigate to second route when tapped.
          },
        ),
      ),
    );
  }
}

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: () {
            // Navigate back to first route when tapped.
          },
          child: const Text('Go back!'),
        ),
      ),
    );
  }
}

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

#

要切换到新路由,请使用 Navigator.push() 方法。push() 方法将一个 Route 添加到由 Navigator 管理的路由堆栈中。Route 从何而来?你可以创建自己的,或者使用平台特定的路由,例如 MaterialPageRouteCupertinoPageRoute。平台特定的路由很有用,因为它使用平台特定的动画过渡到新路由。

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

dart
// Within the `FirstRoute` widget:
onPressed: () {
  Navigator.push(
    context,
    MaterialPageRoute<void>(
      builder: (context) => const SecondRoute(),
    ),
  );
}

dart
// Within the `FirstRoute` widget:
onPressed: () {
  Navigator.push(
    context,
    CupertinoPageRoute<void>(
      builder: (context) => const SecondRoute(),
    ),
  );
}

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

#

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

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

dart
// Within the 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<void>(
                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!'),
        ),
      ),
    );
  }
}

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<void>(
                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!'),
        ),
      ),
    );
  }
}

其他导航方法

#

本主题中的教程向您展示了一种导航到新屏幕并返回到上一个场景的方法,使用 Navigator 类中的 pushpop 方法,但是您可以使用其他几个 Navigator 静态方法。以下是其中几个:

  • pushAndRemoveUntil:将导航路由添加到堆栈,然后从堆栈中移除最近的路由,直到满足条件。
  • pushReplacement:将堆栈顶部的当前路由替换为新路由。
  • replace:用另一个路由替换堆栈上的路由。
  • replaceRouteBelow:替换堆栈上特定路由下方的路由。
  • popUntil:移除添加到导航路由堆栈中的最新路由,直到满足条件。
  • removeRoute:从堆栈中移除特定路由。
  • removeRouteBelow:移除堆栈上特定路由下方的路由。
  • restorablePush:恢复已从堆栈中移除的路由。