Re:birth エンジニアリング

Flultterとテックブログと時々iOS

Flutterで画面遷移に使うNavigatorについて学習する

本日は複数画面の切り替え機能である「ナビゲーション機能」について学習します。 ナビゲーション機能はNavigatorというクラスが用意されているようです。 iOSでいうところのUINavigationControllerみたいなものだと推測しています。

Navigator クラスについて

端的に説明するとNavigatorクラスは次の2つのメソッドを覚えればいいそうです。

画面切替先にプッシュする時

Navigator.push([BuildContext], [Route]);

前の画面に戻る時

Navigator.pop([BuildContext]);

サンプルコードについて

では早速サンプルコードを書いていきます。

main.dart

import 'package:flutter/material.dart';
import 'package:practice_app/first_screen.dart';

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

class MyApp extends StatelessWidget {
  final title = 'Navigatorのサンプルコード';
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      debugShowCheckedModeBanner: true,
      title: 'Navigator App',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
        primaryColor: const Color(0xff2196f3),
        accentColor: const Color(0xff2196f3),
        canvasColor: const Color(0xfffafafa),
      ),
      home: FirstScreen(),
    );
  }
}

first_screen.dart

import 'package:flutter/material.dart';
import 'package:practice_app/second_screen.dart';

class FirstScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('First'),
      ),
      body: Center(
        child: Text('First View'),
      ),
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: 1,
        items: <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            title: Text('First'),
            icon: Icon(Icons.home),
          ),
          BottomNavigationBarItem(
            title: Text('Second'),
            icon: Icon(Icons.navigate_next),
          ),
        ],
        onTap: (int value) {
          if (value == 0) {
            /// First Icon が押されたときは何も起きない
          } else if (value == 1) {
            /// Second Icon が押されたときは画面先にプッシュする
            Navigator.of(context).push(
              MaterialPageRoute(
                builder: (context) {
                  return SecondScreen();
                }
            )
            );
          }
        },
      ),
    );
  }
}

second_screen.dart

import 'package:flutter/material.dart';

class SecondScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Next Screen"),
      ),
      body: Center(
        child: Text('Next'),
      ),
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: 0,
        items: <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            title: Text('First'),
            icon: Icon(Icons.navigate_before)
          ),
          BottomNavigationBarItem(
            title: Text('Second'),
            icon: Icon(Icons.android)
          ),
        ],
        onTap: (int value) {
          if (value == 0) {
            /// First Icon が押されたときは前の画面に戻る
            Navigator.of(context).pop();
          }
        },
      ),
    );
  }
}

今回はmain.dart, first_screen.dart, second_screen.dartの3つのクラスを使っています。 画面遷移の方法としてBottomNavigationBarを作成してiOSでいうところのUITabbarControllerを使ってTabbarを設置しました。

f:id:qed805:20200130074846p:plain
プロジェクトファイルの構成

これでアプリをビルドすると下の方は画面が表示されます。

f:id:qed805:20200130075058p:plain
First Screenの画面

f:id:qed805:20200130075121p:plain
Second Screen の画面

下のタブバーのボタンをタップするとそれぞれの画面が表示されます。

MaterialPageRoute について

MaterialPageRoute というのは PageRouteのサブクラスです。 さらにPageRouteというのはRouteのサブクラスです。 つまり、Routeのサブクラスです。 PageRouteクラスは、現在の画面情報だけでなくプッシュ先の画面情報も保存しているクラスになります。 簡単に言えば、画面情報や移動先の情報を保存している感じになります。 MaterialPageRouteの呼び出しにはbuilderという引数があります。 builderWidgetBuilderという関数シグネーチャーを引数に指定します。 今回はSecondScreenにプッシュさせますのでこちらを指定しています。 これでSecondScreen に画面遷移させることができます。

今回は画面遷移について学びましたが、Flutter では「ルーティング」の概念に位置づけれられいるそうです。 下記のリンクは日本語でのFlutter の画面遷移の解説がされています。 これを見ればWebでいうところの「ルーティング」と一緒ということが分かります。

flutter.ctrnost.com

ということで今回は以上になります。