[読書会]新しい画面に移動して戻る

1.概要

 Flutterの画面遷移に関する基本的なコンセプトについて触れています。

(1)新しい画面に移動し、戻る

 多くのアプリは、異なる種類の情報を表示する複数の画面(ルート)を持っています。
(例えば、ショッピングアプリでは、製品一覧を表示する画面があり、ユーザーが製品の画像をタップすると、詳細画面に遷移して、その製品に関する情報が表示されます。)

(2)用語説明

 Flutterでは、スクリーン(画面)やページのことをルート(Route)と呼びます。
以降、このレシピでも「ルート」という言葉を使用しています。

  • Android では、ルートは Activity に相当します。
  • iOS では、ルートは ViewController に相当します。
  • Flutter では、ルートは単に ウィジェット(Widget) のことを指します。

(3)ルートとNavigator

 Flutterでは、新しいルート(画面)に移動する際に、Navigator を使用します。
Navigator は、画面間の遷移を管理し、スタック(画面の履歴)を管理する役割を担っています。

  • 新しいルートへ移動する
     Navigator.of(context).push() を使って新しい画面をスタックに積み、表示します。
  • 前のルートに戻る
     Navigator.of(context).pop() を使って、スタックから現在の画面を削除し、前の画面に戻ります。

 このように、Navigatorを使って画面遷移を行うことで、ユーザは情報の詳細画面に移動したり、前の画面に戻ったりすることが可能です。

 この基本的な遷移の考え方は、AndroidやiOSのネイティブ開発でのActivityやViewControllerに似ており、FlutterではそれがWidgetとして扱われるという点が特徴的です。

 Flutterでは、これらの画面遷移に関する機能を直感的に実装できるため、アプリ開発においてルートの管理が簡単に行えます。

2.2つのルートの作成

 2つの異なるルート(画面)を作成し、それらの間を遷移するためのボタンを追加する方法が説明されています。
(ここでは、各ルートには1つのボタンがあり、1つ目のルートのボタンを押すと2つ目のルートに遷移し、2つ目のルートのボタンを押すと1つ目のルートに戻るように設計されています。)

(1)FirstRoute クラスの作成

 FirstRoute という名前のクラスが StatelessWidget を継承して作成されています。
このクラスでは、Scaffold ウィジェットを使用して基本的な画面構成を行っています。
AppBar にはタイトルとして “First Route” が表示され、中央にはボタン(ElevatedButton)が配置されています。

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

(2)SecondRoute クラスの作成

 SecondRoute という名前のもう1つのクラスも同様に StatelessWidget を継承して作成されており、同様に Scaffold ウィジェットを使用して画面構成がされています。こちらも中央にボタンが配置され、”Go back!” と表示されています。このボタンを押すと、最初のルートに戻る設計になっています。

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

(3)まとめ

  • FirstRoute では、Navigator.of(context).push() を使用して SecondRoute に遷移します。
  • SecondRoute では、Navigator.of(context).pop() を使用して FirstRoute に戻ります。

 次のステップでは、onPressed 内で Navigator を使って実際の画面遷移を実装しますが、この部分ではまだ遷移ロジックは追加されていません。このサンプルの目的は、Flutterで2つの画面(ルート)を作成する方法を示し、次に画面遷移の仕組みを紹介することです。

3.Navigator.push() を使用した2番目のルートへの移動

 新しいルートに切り替えるには、Navigator.push() メソッドを使用します。
push()メソッドは、Navigatorが管理するルートのスタックにRouteを追加します。
Routeはどこから来るのか? 独自に作成するか、MaterialPageRoute を使用します。
プラットフォーム固有のアニメーションを使用して新しいルートに遷移するので便利です。
FirstRoute ウィジェットの build() メソッドで、onPressed() コールバックを更新します。

Dart
//Navigator.push() を使用した2番目のルートへの移動
onPressed: () {
  Navigator.push(
    context,
    MaterialPageRoute(builder: (context) => const SecondRoute()),
  );
}

4.Navigator.pop() を使用した最初のルートへの復帰

 新しいルートに切り替えるには、Navigator.push() メソッドを使用します。
push()メソッドは、Navigatorが管理するルートのスタックにRouteを追加します。
Routeはどこから来るのか? 独自に作成するか、MaterialPageRoute を使用します。
プラットフォーム固有のアニメーションを使用して新しいルートに遷移するので便利です。
FirstRoute ウィジェットの build() メソッドで、onPressed() コールバックを更新します。

Dart
// Navigator.pop() を使用した最初のルートへの復帰
onPressed: () {
  Navigator.pop(context);
}

5.インタラクティブな例

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

コメントを残す