画面遷移の基本
Flutterで採用している画面遷移の方法は多くのアプリケーションで採用している概念と同じです。そのため、まず、画面遷移の概念から説明します。図1は、画面遷移における基本的な考え方を示したものです。
アプリケーションでは画面状態をスタックで管理しています。ある画面Aから、画面Bに遷移する場合には、このスタックに画面Bを追加します。この行為をPUSHと呼びます。また、遷移した画面Bから画面Aに戻るには、先ほど追加した画面Bを取り出すことで、その前の画面Aが結果的に表示されます。この行為をPOPと呼びます。
一方、画面遷移していくなかで、前の画面を常にスタックに追加していくと、戻る処理で1つ前に戻ってしまうと都合が悪い場合があります。例えば、前の画面に戻したくないようなアンケートやゲームなどの場合です。その場合、図2のように画面遷移をするときに、現在の画面を取り出してから、新たな画面を追加します。
そして、最後にこれまでの画面遷移をまとめて取り出したあとに、新たな画面を追加する場合の例です。このようなケースは、ウィザード形式やステップ形式と呼ばれるものもあります。
例えば、ECショップで購入処理を行う場合、途中の個人情報や配送先などの入力している最中は画面を戻ることが必要となります。しかし、最終的な購入確定を行ったあとは、途中の画面に戻れません。そのようなケースが図3です。
このような画面遷移のパターンを押さえておけば、基本的な部分はカバーできます。あとは、これらの組み合わせや、多少の応用で多くのことは実現可能です。
画面遷移方法
Flutterで画面遷移を制御するにはNavigatorクラスを利用します。このクラスを使った画面遷移をするコードを説明します。
画面への遷移と戻る処理
Navigatorクラスのpush/popを使った基本的な画面遷移のサンプルを示したものが、図4です。
画面を遷移する場合のコードを示したコードはリスト1です。
class HomePage extends StatelessWidget{ @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("ホーム"), ), body: Center( child: TextButton( child: Text("1ページ目に遷移する"), onPressed: (){ // (1) 指定した画面に遷移する Navigator.push(context, MaterialPageRoute( // (2) 実際に表示するページ(ウィジェット)を指定する builder: (context) => FirstPage() )); }, ), ), ); } }
画面遷移する際には、(1)pushメソッドの第一引数には、BuildContextを指定し、第二引数にRouteを指定します。このRouteクラスが画面スタックとして管理されているものになります。また、このRouteクラスでは、画面が切り替わる際のアニメーションなども管理しています。
FlutterではMaterialPageRouteという既存のRouteクラスが用意されているので、多くの場合にはこのクラスを利用します。MaterialPageRouteクラスには、(2)のようにbuilderプロパティで指定する関数で画面ウィジェットを作成します。
続いて、前の画面に戻る場合のコードを示したものがリスト2です。
class FirstPage extends StatelessWidget{ @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title : Text("ページ(1)") ), body : Center( child: TextButton( child: Text("最初のページに戻る"), // (1) 前の画面に戻る onPressed: (){ Navigator.pop(context); }, ), ) ); } }
前の画面に戻る場合には単純で、(1)のようにpopメソッドを使うだけです。
画面の置き換えと指定した画面に戻る
現在の画面と新規の画面の置き換えをする場合の画面遷移と指定した画面まで戻る場合のサンプルを示したものが図5です。
「ページ(1)」と「ページ(2)」を置き換える場合には、リスト3のようにpushReplacementメソッドを使います。
onPressed: (){ Navigator.pushReplacement( context, MaterialPageRoute( builder: (context) => SecondPage(), )); }
また、指定した画面まで画面スタックをクリアした上で画面を戻る場合には、リスト4のようにpopUntilメソッドを使います。
onPressed: (){ Navigator.popUntil(context, (route) => route.isFirst); }
このサンプルコードの場合には、最初の画面まで戻ることができます。任意の場所まで戻るためには、第2引数に独自のRoutePredicat実装を指定する必要があります。これは少々、面倒になるので、後述するように画面名を用いた画面管理を用いる方法をおすすめします。