ページのナビゲーション 〜 ラウト設定と Navigator の pushNamed

ここでは Drawer 内のリンクから他のスクリーンに移動する例を示します。

画像はあらかじめアセットに追加しています。(「画像の利用方法」を参考にしてください)

ラウトの設定

route はラウト?ルート?

日本語では route をルートと書く場合も多いと思いますが、当サイトでは route をラウトと書いてます。理由は2つあります。

ひとつ目の理由はアメリカ英語では「ラウト」に近い発音の方が一般的であるためです。ネットワーク機器のルーター (router) はアメリカ発音では「ラウター」です。ブリティッシュでは「ルート」っぽい発音の一択のようですが、当方は米国在住で、イギリスのことは知りません。

ふたつめの理由は、ルートと書くと root と紛らわしいからです。「ルートを使うとスクリーン遷移できます」と言われたら、「そうなのかパーミッションの設定が必要なのだな」と 思ってしまいそうです。しかし「ラウトを使うとスクリーン遷移できます」なら route の設定をすることがより明確に区別できるでしょう。

もしかしたら、日本でカタカナで話すときはルートと言う方がいいかもしれません。しかしながら、上述の理由で一般的ではないかもしれないと思いつつも、わざわざラウトと書いています。

画面遷移の情報、すなわちラウトの情報は、MaterialApp の routes プロパティに設定します。

main.dart では次のように、ラウトの設定を次のように行います。Navigator で使う識別用の文字列と、 スクリーン (ウィジェット) の生成方法を記述します。

import 'package:flutter/material.dart';
import './pages/home-page.dart';
import './pages/place-page.dart';
import './pages/settings-page.dart';

void main() => runApp(
      MaterialApp(
        debugShowCheckedModeBanner: false,
        routes: <String, WidgetBuilder>{
          '/home': (BuildContext context) => HomePage(),
          '/place': (BuildContext context) => PlacePage(),
          '/settings': (BuildContext context) => SettingsPage(),
        },
        home: HomePage(),
      ),
    );

この情報は下の、ドロワー (Drawer) で使います。

グローバルストアの作成

タップするリンクによって画像とタイトルを切り替えている箇所については、シングルトンのグローバルストアを用意しておき、ドロワーのタップハンドラでセットした値を、移動先のページで参照しています。 こうしたデータストアの作成方法については「シングルトンによるデータストアの実装」を参考にしてください。

ファイル名は item_store.dart としています。

class ItemStore {
  static final Map<String, dynamic> _items = <String, dynamic>{};
  static final ItemStore _cache = ItemStore._internal();

  factory ItemStore() {
    return _cache;
  }

  ItemStore._internal();

  set(String key, dynamic value) => _items[key] = value;
  get(String key) => _items[key];
}

ドロワーの設定

Drawer はホームスクリーンのウィジェット内で作成しています。

パスとファイル名は pages/home-page.dart です。

import 'package:flutter/material.dart';
import '../item_store.dart';

class HomePage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _HomePageState();
  }
}

class _HomePageState extends State<HomePage> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('Drawer Test'),
        ),
        drawer: Drawer(
          child: ListView(
            children: <Widget>[
              DrawerHeader(
                child: Text(
                  'My App',
                  style: TextStyle(
                    fontSize: 24,
                    color: Colors.white,
                  ),
                ),
                decoration: BoxDecoration(
                  color: Colors.blue,
                ),
              ),
              ListTile(
                title: Text('Home'),
                onTap: () {
                  Navigator.pop(context);
                  Navigator.pushNamed(context, '/home');
                },
              ),
              Divider(),
              ListTile(
                title: Text('Huntington Beach'),
                onTap: () {
                  ItemStore()
                      .set('image', 'assets/images/huntington-beach.jpg');
                  ItemStore().set('title', 'Huntington Beach');
                  Navigator.pushNamed(context, '/place');
                },
              ),
              ListTile(
                title: Text('Torrance Beach'),
                onTap: () {
                  ItemStore().set('image', 'assets/images/torrance-beach.jpg');
                  ItemStore().set('title', 'Torrance Beach');
                  Navigator.pushNamed(context, '/place');
                },
              ),
              Divider(),
              ListTile(
                title: Text('Settings'),
                onTap: () {
                  Navigator.pop(context);
                  Navigator.pushNamed(context, '/settings');
                },
              ),
            ],
          ),
        ),
        body: Center(
          child: Text(
            'Home',
            style: TextStyle(
              fontSize: 32,
            ),
          ),
        ));
  }
}

「スクリーン」 あるいは「ページ」などと呼ばれる画面情報は、Flutter では「ラウト」として扱います。 Navigator ウィジェットでラウトを管理します。

Navigator ウィジェットの push メソッドと pop メソッドでラウトのスタックを操作できます。上で使っている pushNamed メソッドを使うと、 MaterialApp の routes プロパティで設定したラウトの名前で、ラウトスタックにラウトをプッシュできます。

その他のページ

その他、このサンプルで使っているテストページは次の通りです。今回は PlacePage というウィジェットで画像を読み込んでます。ビーチの写真を表示しているところです。

pages/place-page.dart

import 'package:flutter/material.dart';
import '../item_store.dart';

class PlacePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(ItemStore().get('title')),
      ),
      body: Center(
        child: Center(
          child: Image.asset(
            ItemStore().get('image'),
          ),
        ),
      ),
    );
  }
}

pages/settings-page.dart

import 'package:flutter/material.dart';

class SettingsPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Settings'),
      ),
      body: Center(
        child: Text('Settings Page'),
      ),
    );
  }
}

以上、ラウトの設定と Navigator を利用して、画面遷移する例を示しました。

ここまでお読みいただき、誠にありがとうございます。SNS 等でこの記事をシェアしていただけますと、大変励みになります。どうぞよろしくお願いします。

© 2024 Flutter 入門