导航到一个新页面和返回

我们通常会用“屏”来表示应用的不同页面(界面)。比如,某个应用有一“屏”展示商品列表,当用户点击某个商品的图片,会跳到新的一“屏”展示商品的详细信息。

在 Android 开发中,Activity 相当于“路由”,在 iOS 开发中,ViewController 相当于“路由”。在 Flutter 中,“路由”也是一个 widget。

怎么样从一个“路由”跳转到新的“路由”呢?Navigator 类。

这个教程里我们使用 Navigator 来跳转到一个新的“路由”:

步骤

下面来展示如何在两个路由间跳转,总共分三步:

  1. 创建两个路由

  2. 用 Navigator.push() 跳转到第二个路由

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

1. 创建两个路由

首先,我们来创建两个路由。这是个最简单的例子,每个路由只包含一个按钮。点击第一个路由上的按钮会跳转到第二个路由,点击第二个路由上的按钮,会回退到第一个路由。

首先来编写界面布局代码:

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

2. 用 Navigator.push() 跳转到第二个路由

使用 Navigator.push() 方法跳转到新的路由, push() 方法会添加一个 Route 对象到导航器的堆栈上。那么这个 Route 对象是从哪里来的呢?你可以自己实现一个,或者直接使用 MaterialPageRoute 类。使用 MaterialPageRoute 是非常方便的,框架已经为我们实现了和平台原生类似的切换动画。

FirstRoute widget 的 build() 方法中,我们来修改 onPressed() 回调函数:

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

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

怎么关闭第二个路由回退到第一个呢? 使用 Navigator.pop() 方法, pop() 方法会从导航器堆栈上移除 Route 对象。

实现返回第一个页面,更新 SecondRoute widget 的 onPressed() 方法回调。

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