【Flutter】ページ遷移、ページ切り替え【日本語】

Flutterでページ遷移、ページ切り替えを実装していきます。

「戻る」を禁止する方法についても記載します。

他のプログラミングに関する記事はこちら

スポンサーリンク

前提

特になし。

以下の順番で試していきます。

・戻ることの出来るページ遷移(pushNamed)

・戻ることが出来ないページ遷移(一方通行のページ遷移)(pushReplacementNamed)

スポンサーリンク

戻ることの出来るページ遷移(pushNamed)

実装するもの

まずはじめに、戻ることの出来るページ遷移を実装していきます。

以下のような感じのものを作ります。

恐らくSNS系とか便利系アプリ(スケジュール管理だとか何かのデータ整理のためのアプリだとか)にはよくこれを使うと思われます。

 

それでは早速、ページ遷移の方法から。

方法

ページ遷移をさせるにはNavigatorのpushNamedを使います。

イメージ的には、NavigatorのpushNamedでURLを指定して遷移させるようなイメージです。

そして、URLを指定して遷移させるためにはページごとにURLを持たせる必要があります。

なので、まずはURLの設定をmainメソッドの中で指定してあげます。

void main(){
  runApp(new MaterialApp(
    title: 'Test',
    routes: <String, WidgetBuilder>{
      '/': (_) => new Home(),
      '/Page1' : (_) => new Page1(),
    },
  ));
}

この記述により、

URL「/」はHomeクラスの内容を

URL「/Page1」はPage1クラスの内容を

それぞれ表示させるようになります。

そして、「/」にホーム……つまりアプリ起動時に最初に呼ぶ画面を設定します(今回の場合はHomeクラスの内容が最初に表示されます)

 

 

次に、アプリ起動時に呼び出されるHomeを作成していきます。

class Home extends StatelessWidget { 
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'otameshi',
      home: Scaffold(
        appBar: AppBar(
          title: Text('PageTest'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.start, //上寄せ
            crossAxisAlignment: CrossAxisAlignment.start, //左寄せ
            children: <Widget>[
              GestureDetector(
                onTap: () {
                  Navigator.of(context).pushNamed("/Page1");
                },
                child: Text("ページ切り替え1"),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

テキスト「ページ切り替え1」をタップしたときに、Navigator.of(context).pushNamed(“/Page1”);でURL「/Page1」に遷移させています。

事前にmainメソッド内で「/Page1」の時には「Page1」クラスの内容を表示させるように設定していますので、これでページ遷移の準備が整ったことになります。

 

 

最後に「Page1」クラスを作成します。

class Page1 extends StatelessWidget { 
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'otameshi',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Page1'),
        ),
        body: Column(
          mainAxisAlignment: MainAxisAlignment.start, //上寄せ
          crossAxisAlignment: CrossAxisAlignment.start, //左寄せ
          children: <Widget>[
            Text("ページ1を表示",),
            GestureDetector(
              onTap: () {
                Navigator.of(context).pop(true);
              },
              child: Text("popで前画面に戻る"),
            ),
          ],
        )
          
      ),
    );
  }
}

Page1クラスでは前画面に戻るための「Navigator.of(context).pop(true);」を設定しています。

「popで前画面に戻る」をタップした際に「Navigator.of(context).pop(true);」が行われ、前画面に戻ります。

ページ遷移に比べ前画面に戻るだけであれば「Navigator.of(context).pop(true);」を呼び出すだけでいいので、簡単です。

 

結果、以下のような感じになります。

※Androidには元々戻るボタン(◀)があるので、それを押したときにも同じように戻れます。

スポンサーリンク

戻ることが出来ないページ遷移(一方通行のページ遷移)(pushReplacementNamed)

次に、一方通行のページ遷移の方法を記載していきます。

ゲームアプリでタイトル画面から実際のゲーム画面に移るとき等に使う……と思います。

正直なところ、pushReplacementNamedとpushNamedの使い分けについて正確に理解してません。

実装するもの

前項で作成したアプリに追加で「ページ2」というのを作成し、以下のようなアプリに更新してみます

※前画面に戻れていますが後述します

方法

まずは新しいページを用意するために、mainメソッド内にPage2へ遷移させるための前準備を行います。

この操作は前項でやったことと同じです。

void main(){
  runApp(new MaterialApp(
    title: 'Test',
    routes: <String, WidgetBuilder>{
      '/': (_) => new Home(),
      '/Page1' : (_) => new Page1(),
      '/Page2' : (_) => new Page2(), //新しく追加した行
    },
  ));
}

この記述により、「/Page2」に遷移させたらPage2クラスの内容が呼び出されるようになります。

 

 

次も前項と同じです。

最初に呼び出されるHomeクラス(URLが「/」のクラス)内で、Page2へ遷移させるための記述を行います。

class Home extends StatelessWidget { 
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'otameshi',
      home: Scaffold(
        appBar: AppBar(
          title: Text('PageTest'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.start, //上寄せ
            crossAxisAlignment: CrossAxisAlignment.start, //左寄せ
            children: <Widget>[
              GestureDetector(
                onTap: () {
                  Navigator.of(context).pushNamed("/Page1");
                },
                child: Text("ページ切り替え1"),
              ),
              GestureDetector(
                onTap: () {
                  Navigator.of(context).pushReplacementNamed("/Page2");
                },
                child: Text("ページ切り替え2"),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

21~26行目にPage2へ遷移させるための処理を追加しました。

一方通行のページ遷移をさせるためには、NavigatorのpushReplacementNamedを使います。

あとは遷移先であるPage2クラスをPage1クラスと同じように作成してあげれば完了です。

 

 

ちなみに、pushReplacementNamedを使って遷移した後にpopやAndroidにある戻るボタン(◀)で戻るとアプリが止まります。

※以下例は「popで前画面に戻る」をタップした際にpopで前画面に戻ろうとしています

なので、pushReplacementNamedを使った場合はpopで戻ることがないような設計にしましょうね。

スポンサーリンク

補足1:Androidに元からある戻るボタンを禁止する

pushReplacementNamedを使ってページ遷移させた時用に、Androidの戻るボタンを禁止させる方法を記載します。

Androidの戻るボタンを禁止するには、ScaffoldをWillPopScopeで囲みます。

そして、WillPopScopeのonWillPopで() async => falseを設定すればOKです。

 

……と、文字にすると難解ですが、以下みたいな感じで作ればよいだけです。

class Page2 extends StatelessWidget { 
  @override
  Widget build(BuildContext context) {
    return new WillPopScope(
      onWillPop: () async => false,
      child:Scaffold(
        //Scaffoldの内容を記述する
      ),
    );
  }
}

スポンサーリンク

補足2:pushReplacementNamedで遷移した後に戻る

pushReplacementNamedで遷移した場合「戻る」ことは出来ませんが、再びpushReplacementNamedしたページに遷移することで疑似的に戻ることが可能です。

※多分pushReplacementNamedはただ単に元いたページ情報を破棄しているだけ

 

以下のような記述をすれば、元いたホームに戻ることが可能です。

class Page2 extends StatelessWidget { 
  @override
  Widget build(BuildContext context) {
    return new WillPopScope(
      onWillPop: () async => false,
      child:Scaffold(
        appBar: AppBar(
          title: Text('Page2'),
        ),
        body: Column(
          mainAxisAlignment: MainAxisAlignment.start, //上寄せ
          crossAxisAlignment: CrossAxisAlignment.start, //左寄せ
          children: <Widget>[
            Text("ページ2を表示"),
            GestureDetector(
              onTap: () {
                Navigator.of(context).pop(true);
              },
              child: Text("popで前画面に戻る"),
            ),
            GestureDetector(
              onTap: () {
                Navigator.of(context).pushNamed("/");
              },
              child: Text("pushで戻る"),
            ),
          ],
        )
      ),
    );
  }
}

21~26行目の内容がpushで戻っている状態です。

上記のような記述を行えば、pushReplacementNamedで破棄したページにまた戻る(正確には再度遷移している)ことが可能です。

スポンサーリンク

まとめ

お疲れさまでした。以上で終了です。

最後に、今回の記事で作成した最終的な全コードを載せておきます。

import 'package:flutter/material.dart';

void main(){
  runApp(new MaterialApp(
    title: 'Test',
    routes: <String, WidgetBuilder>{
      '/': (_) => new Home(),
      '/Page1' : (_) => new Page1(),
      '/Page2' : (_) => new Page2(),
    },
  ));
}

class Home extends StatelessWidget { 
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'otameshi',
      home: Scaffold(
        appBar: AppBar(
          title: Text('PageTest'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.start, //上寄せ
            crossAxisAlignment: CrossAxisAlignment.start, //左寄せ
            children: <Widget>[
              GestureDetector(
                onTap: () {
                  Navigator.of(context).pushNamed("/Page1");
                },
                child: Text("ページ切り替え1"),
              ),
              GestureDetector(
                onTap: () {
                  Navigator.of(context).pushReplacementNamed("/Page2");
                },
                child: Text("ページ切り替え2"),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

class Page1 extends StatelessWidget { 
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'otameshi',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Page1'),
        ),
        body: Column(
          mainAxisAlignment: MainAxisAlignment.start, //上寄せ
          crossAxisAlignment: CrossAxisAlignment.start, //左寄せ
          children: <Widget>[
            Text("ページ1を表示",),
            GestureDetector(
              onTap: () {
                Navigator.of(context).pop(true);
              },
              child: Text("popで前画面に戻る"),
            ),
          ],
        )
          
      ),
    );
  }
}

class Page2 extends StatelessWidget { 
  @override
  Widget build(BuildContext context) {
    return new WillPopScope(
      onWillPop: () async => false,
      child:Scaffold(
        appBar: AppBar(
          title: Text('Page2'),
        ),
        body: Column(
          mainAxisAlignment: MainAxisAlignment.start, //上寄せ
          crossAxisAlignment: CrossAxisAlignment.start, //左寄せ
          children: <Widget>[
            Text("ページ2を表示"),
            GestureDetector(
              onTap: () {
                Navigator.of(context).pop(true);
              },
              child: Text("popで前画面に戻る"),
            ),
            GestureDetector(
              onTap: () {
                Navigator.of(context).pushNamed("/");
              },
              child: Text("pushで戻る"),
            ),
          ],
        )
      ),
    );
  }
}

他のプログラミングに関する記事

プログラミングまとめ

プログラミングに関する記事です。 言語とかツールごとにまとめています。 スポンサーリンク [adcode] Flutter ・簡単導入~サンプルアプリのデバック起動まで ・文字の表示(重ねて[…]

IMG

スポンサーリンク