跳至主要內容

導覽至新畫面並返回

大多數應用程式都包含多個畫面,以顯示不同類型的資訊。例如,應用程式可能有一個顯示產品的畫面。當使用者點擊產品的影像時,新的畫面會顯示有關產品的詳細資訊。

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

2. 使用 Navigator.push() 導覽至第二個路由

#

要切換到新的路由,請使用 Navigator.push() 方法。push() 方法會將一個 Route 新增到由 Navigator 管理的路由堆疊中。Route 是從哪裡來的?您可以建立自己的,或者使用 MaterialPageRoute,它很有用,因為它會使用特定於平台的動畫轉換到新路由。

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

dart
// Within the `FirstRoute` widget:
onPressed: () {
  Navigator.push(
    context,
    MaterialPageRoute(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(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!'),
        ),
      ),
    );
  }
}
#

在先前的範例中,您學習了如何使用 MaterialPageRoute (來自 Material Components) 在螢幕之間導航。然而,在 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!'),
        ),
      ),
    );
  }
}