Flutter入門-勉強メモ003-【始めての画面遷移】-

今回は, 次のようにボタンを押すと次の画面にいく(画面遷移)アプリを作成していきます. まぁ, 今回もアプリと呼べるものではないですが…

Flutter
Flutter

これも公式サイトに丁寧な説明があります. Flutterは本当にドキュメントが充実しています.

Pierrotのアイコン画像Pierrot

このページいらない?(;-_-)

目次

1つのファイルにおいての画面遷移

Flutterにおける画面遷移は, Navigatorクラスを用いて行います.

  • Navigator.push()メソッドで次の画面に移ります
  • Navigator.pop()メソッドで前の画面に戻ります

このメソッド名からわかるように, Flutterでは画面をスタックしていきます. つまり, 新しい画面を古い画面の上にかぶせて表示させています.

前の画面に戻るときは, 積み上げた画面を取り除くようなイメージになります.

1つのファイルにすべて書くと次のようになります.

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomeScreen(),
    );
  }
}

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('最初の画面'),
        centerTitle: true,
      ),
      body: Center(
        child: RaisedButton(
          child: Text("次の画面に移動します"),
          onPressed: () {
            Navigator.push(
              context,
              MaterialPageRoute(
                builder: (context) => NextScreen(),
              ),
            );
          },
        ),
      ),
    );
  }
}

// 次のページ
class NextScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("次の画面"),
        centerTitle: true,
      ),
      body: Center(
        child: Text("次の画面にきました!"),
      ),
    );
  }
}

画面遷移は,

Navigator.push(
              context,
              MaterialPageRoute(
                builder: (context) => NextScreen(),
              ),

で実行されます. Flutterの公式サイトを見ると, Navigator.push()は次のようになっています.

Future<T> push <T extends Object>(BuildContext context, Route<T> route)

contextはウィジェットツリーの中で自分がどの位置にいるのか把握するのに役立ちます.

また, 引数にRouteを渡しますが, ほとんどがMaterialPageRouteのインスタンスを渡します.

引数はマテリアルデザインにのっとった振る舞いにしたいので, MaterialPageRouteにしていますが, MaterialPageRouteでなくてもかまいません. CupertinoPageRouteにすればiOS風の振る舞いになります. 他のクラスを作成することも可能です.

その中のbuilderプロパティで遷移させる画面を指定します.

実行結果の2枚目のAppBarを見ればわかるように, AppBarに自動的に「←」ボタンが実装され, 前の画面に簡単に戻ることができます. これもFlutterのウィジェットの素晴らしいところです.

Dartファイルを画面ごとに分割させた場合の画面遷移

実際の開発において1つのファイルにすべてのコードを書くことはなく, ファイル分割をして書いていきます.

ここでは, 動きは先ほどと同じですが, 文字の大きさやボタンの配色は変更した上でファイルを分割していきます.

ファイル分割次のように分割します.

  1. main.dart→これがメインファイル(説明になっていませんが笑)
  2. home_screen.dart→最初の画面の実装
  3. next_screen.dart→次の画面の実装

保管は以下の通りです.

Flutter

3つのファイルのコードはそれぞれ次の通りです.

import 'package:flutter/material.dart';
import 'screens/home_screen.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false, //右上のDEBUGというバナーを表示させない
      title: "最初の画面",
      home: HomeScreen(),
    );
  }
}
import 'package:flutter/material.dart';
import 'next_screen.dart';

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: RaisedButton(
          child: Text(
            "次の画面へ",
            style: TextStyle(
              fontSize: 18.0,
              fontWeight: FontWeight.bold,
            ),
          ),
          onPressed: () => _nextScreen(context),
          color: Colors.blueAccent,
          textColor: Colors.white,
        ),
      ),
    );
  }

  _nextScreen(BuildContext context) {
    Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => NextScreen(),
      ),
    );
  }
}
import 'package:flutter/material.dart';

class NextScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("次の画面"),
        centerTitle: true,
      ),
      body: Center(
        child: Text(
          "次の画面にきました!",
          style: TextStyle(fontSize: 18.0),
        ),
      ),
    );
  }
}

先ほどと同じようにボタンを押すと次の画面に移るというシンプルなものです.

main.dartでhome_screen.dartが読み込まれ, 最初の画面が立ち上がります. 「次の画面へ」のボタンが押されると, _nextScreen()メソッドが働き, NextScreen()が呼び出されます.

Flutter
Flutter

元のページに戻るボタンを追加する

次のように, next_screenに「前の画面に戻る」ボタンを実装してみます.

Flutter

元のページに戻る場合はpopメソッドを使います.

next_screen.dartを次のように書き換えれば実装できます.

import 'package:flutter/material.dart';

class NextScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("次の画面"),
        centerTitle: true,
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              "次の画面にきました!",
              style: TextStyle(fontSize: 18.0),
            ),
            SizedBox(
              height: 20.0,
            ),
            RaisedButton(
              child: Text(
                "前の画面へ戻る",
                style: TextStyle(
                  fontSize: 18.0,
                  fontWeight: FontWeight.bold,
                ),
              ),
              onPressed: () {
                Navigator.pop(context);
              },
              color: Colors.blueAccent,
              textColor: Colors.white,
            ),
          ],
        ),
      ),
    );
  }
}

元の画面に戻る場合,

Navigator.pop(context);

で戻れます. いやはや, 便利.

名前付きの画面遷移

画面が複数ある場合, 画面ごとに名前をつけて, その名前を利用してページにアクセスすることもできます. Webページのようですね. これは実際に具体例を見てもらったほうが早いかもしれません.

main.dartとhome_screen.dartの2つを変更していきます.

import 'package:flutter/material.dart';
import 'screens/home_screen.dart';
import 'screens/next_screen.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false, //右上のDEBUGというバナーを表示させない
      title: "最初の画面",
      initialRoute: '/',
      routes: {
        '/': (context) => HomeScreen(),
        '/next': (context) => NextScreen(),
      },
    );
  }
}

main.dartでそれぞれのページに名前をつけます.

routesはmap形式(他の言語だとdictionaryですね.)で挿入します. initialRouteで開始画面を定義します. 今回の場合は, home_screen.dartです. これはhomeの代わりをしています. この2つは競合してしまうので, home:は取り除いてあります.

先ほどと違い, home_screen.dartでnext_screen.dartの読み込みの必要はありません.

import 'package:flutter/material.dart';
import 'screens/next_screen.dart';

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: RaisedButton(
          child: Text(
            "次の画面へ",
            style: TextStyle(
              fontSize: 18.0,
              fontWeight: FontWeight.bold,
            ),
          ),
          onPressed: () => _nextScreen(context),
          color: Colors.blueAccent,
          textColor: Colors.white,
        ),
      ),
    );
  }

  _nextScreen(BuildContext context) {
    Navigator.pushNamed(context, '/next');
  }
}

画面の移動は,

Navigator.pushNamed(context,'/next');

の一行で済みます. 画面が複数持つようなアプリ(ほとんどのアプリがそうでしょうが.)では名前付き画面遷移のほうが管理しやすくなります.

名前付き画面においてidを設定する

画面移動の際, 文字列でスクリーン名をつけるとミスにつながります. そこで, 画面ごとにstaticなidを割り振る方法もあります.

import 'package:flutter/material.dart';
import 'screens/home_screen.dart';
import 'screens/next_screen.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false, //右上のDEBUGというバナーを表示させない
      title: "最初の画面",
      initialRoute: HomeScreen.id,
      routes: {
        HomeScreen.id: (context) => HomeScreen(),
        NextScreen.id: (context) => NextScreen(),
      },
    );
  }
}
import 'package:flutter/material.dart';
import 'package:my_first_app/screens/next_screen.dart';

class HomeScreen extends StatelessWidget {
  static const id = 'home_screen';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: RaisedButton(
          child: Text(
            "次の画面へ",
            style: TextStyle(
              fontSize: 18.0,
              fontWeight: FontWeight.bold,
            ),
          ),
          onPressed: () => _nextScreen(context),
          color: Colors.blueAccent,
          textColor: Colors.white,
        ),
      ),
    );
  }

  _nextScreen(BuildContext context) {
    Navigator.pushNamed(context, NextScreen.id);
  }
}

上のコードを見るとわかるように,

static const id = 'home_screen';

で「home_screen」という固有の名前を割り振っています.

import 'package:flutter/material.dart';

class NextScreen extends StatelessWidget {
  static const id = 'next_screen';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("次の画面"),
        centerTitle: true,
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              "次の画面にきました!",
              style: TextStyle(fontSize: 18.0),
            ),
            SizedBox(
              height: 20.0,
            ),
            RaisedButton(
              child: Text(
                "前の画面へ戻る",
                style: TextStyle(
                  fontSize: 18.0,
                  fontWeight: FontWeight.bold,
                ),
              ),
              onPressed: () {
                Navigator.pop(context);
              },
              color: Colors.blueAccent,
              textColor: Colors.white,
            ),
          ],
        ),
      ),
    );
  }
}
この方法だとタイプミスをした場合でもAndroidStudioにそのミスを指摘してもらえます.
次回は画面遷移の際の値の受け渡しについて見ていきます.

コメント

コメントする

目次
閉じる