🦉

Flutterでルート定義をして画面遷移させたい

2021/07/24に公開

Flutterで画面遷移をさせる場合によくあるサンプルだとNavigator.pushを使ったものが多いですが、名前付きのルート定義をしてそれをもとに画面遷移させるパターンを学んだので書いておきます。

環境

  • macOS Big Sur Version 11.3.1
  • Flutter 2.2.0
  • Dart 2.13.0

サンプル

  • ルート定義
import 'package:first_flutter_app/align.dart';
import 'package:first_flutter_app/input_test.dart';
import 'package:first_flutter_app/safe_area_sample.dart';
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'SafeArea Sample',
      theme: ThemeData(
        primaryColor: Colors.white,
      ),
      routes: {
        '/': (context) => SafeAreaSample(),
        '/page1': (context) => AlignTestPage(),
        '/page2': (context) => InputTest(),
      },
    );
  }
}
  • 定義したルートを使って遷移させる
import 'package:flutter/material.dart';

class SafeAreaSample extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('SafeAreaSample'),
      ),
      body: SafeArea(
        bottom: false,
        child: Center(
          child: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              TextButton(
                child: Text(
                  'Go to page1',
                  style: TextStyle(color: Colors.black),
                ),
                style: TextButton.styleFrom(
                  backgroundColor: Colors.amber,
                ),
                onPressed: () {
                  Navigator.pushNamed(context, '/page1');
                },
              ),
              SizedBox(
                width: 10,
              ),
              TextButton(
                child: Text(
                  'Go to page2',
                  style: TextStyle(color: Colors.black),
                ),
                style: TextButton.styleFrom(
                  backgroundColor: Colors.amber,
                ),
                onPressed: () {
                  Navigator.pushNamed(context, '/page2');
                },
              ),
            ],
          ),
        ),
      ),
    );
  }
}

MaterialApproutesにMap形式でルートを定義する

Mapを使ってキーにルート名、値に遷移させたいページをビルドする関数を登録します。

routes: {
   '/': (context) => SafeAreaSample(),
   '/page1': (context) => AlignTestPage(),
   '/page2': (context) => InputTest(),
},

routesを使って定義したページに遷移させるときは、Navigator.pushNamedを使います。
Mapのキーを指定することで対応したページに遷移させることができます。

TextButton(
   child: Text(
   'Go to page1',
   style: TextStyle(color: Colors.black),
   ),
   style: TextButton.styleFrom(
   backgroundColor: Colors.amber,
   ),
   onPressed: () {
   Navigator.pushNamed(context, '/page1');
   },
),

実際に動かしてみる

Image from Gyazo

感想とメリデメ

本記事の書き方でルート定義をした場合、main.dartを見ればアプリにある全ページを一覧できるので開発時に全体を確認するときに役に立ちそうです。

逆にデメリットとしては、ルート名を変えたいときにコード全体で影響箇所を確認する必要があることくらいですかね?
とはいえ、const切っておいて使えばそこだけ変えればいいし、そもそもそこまで頻繁に変わるものでもないのでデメリットとしては小さい気がします。

むしろ、Navigator.pushNavigator.pushNamedが混ざっているほうがはるかにめんどくさそうです。このへんはプロジェクトでちゃんとルールを決めてどっちかに統一しておかないとページ遷移がカオスになって、あとになってめちゃくちゃ首を締めてきそうな気がします...。

と思っていたら、pushNamedにもデメリットがあるようで
こちらのブログでデメリットを解説されていました。

https://blog.dalt.me/2616

  1. ページの追加が面倒
  2. ページを表示するのに必須パラメータが何かを覚えていないといけない
  3. Navigatorを作った際に、onGenerateRouteで再定義しなければいけない

1.と2.はなるほどなーと理解できたのですが、まだBottomNavigationBarを使ったことがないので3.については自分で試してみる必要がありそうです。

参考

Discussion