大多數應用程式包含多個螢幕以顯示不同型別的資訊。例如,一個應用程式可能有一個顯示產品的螢幕。當用戶點選產品的圖片時,新螢幕會顯示產品的詳細資訊。

在 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:恢復已從堆疊中移除的路由。