BottomNavigationBarウィジェット
Scaffoldの画面下部にメニューを表示する場合には、BottomNavigationBarウィジェットがよく利用されます。
BottomNavigationBarウィジェットでは、メニュータブの表示方法には2つのタイプがあります。その違いを示したものが図3です。
(1)はshiftingタイプといい、アクティブなボタン以外はアイコンのみで表示されます。(2)はfixedタイプといいボタンとラベルが常に表示されます。この設定は、typeプロパティで設定するのですが、設定しない場合には、4つ以上のメニューがある場合には、shiftingになり3つ以下であればfixedになります。
自動で表示方法が変わるところに筆者は少々、びっくりしてしまいました。そのような方は、筆者と同じように必ず指定を明示的にすることをおすすめします。
BottomNavigationBarの利用例(lib/pages/ScaffoldSample.dartの抜粋)] bottomNavigationBar: BottomNavigationBar( // (1) タイプを指定 type: BottomNavigationBarType.shifting, // (2) 表示するメニュー items: [ BottomNavigationBarItem( icon: Icon(Icons.home), label: "ホーム", backgroundColor: Colors.black ), BottomNavigationBarItem( icon: Icon(Icons.star), label : "マイページ", backgroundColor: Colors.black ), // (省略) ], // (3) アクティブなタブ currentIndex: 2, // (4) タップされた時の処理 onTap: (int idx){ // ボタンがタップされた時の処理 }, ),
(1)では先ほど紹介したタイプを明示的に指定しています。そして、(2)のように実際に表示するメニューはitemsプロパティにBottomNavigationBarItemウィジェットの配列として指定します。
また、アクティブな要素は(3)のようにcurrentIndexで指定します。値は0から始まるメニュー配列のインデックス値になります。(4)のようにonTapでタップされたメニューの処理を記述します。
FloatingActionButtonウィジェット
FloatingActionButtonウィジェットは、丸形のボタンを画面上に配置するためのウィジェットです。例えば、上に戻るボタンや、新規作成ボタンをショートカット的な使い方で配置するボタンとしてよく利用されます。
デフォルトでは画面右下に表示されますが、ScaffoldのfloatingActionButtonLocationプロパティを指定することで、実際にはさまざまな場所に配置することができます。
具体的な設置可能な配置場所はAPIドキュメントを参照してください。
リスト3はScaffoldにFloatingActionButtonを追加する場合の実装例です。
floatingActionButton: FloatingActionButton( child: Icon(Icons.add), // (1) 実際に表示するウィジェット tooltip: "追加する", // (2) ツールチップ用の表示文字列 onPressed: (){ // (3) ボタンが押された時の処理 }, ),
(1)で実際に表示するウィジェットを指定します。ここではアイコンを表示しています。また、(2)のtooltipでツールチップ用の表示文字列を指定し、(3)のonPressedではボタンが押された時の処理を記述します。
Drawerウィジェット
Drawerはスワイプで開閉することができるウィジェットです。一般的にはメニューなどを表示します。Drawerは、右から開くDrawerと左から開くDrawerの2種類があります。
左から開く場合には、Scaffoldのdrawerプロパティを利用し、右から開く場合には、endDrawerプロパティを使用します。
drawer: Drawer( child: ListView( children: [ DrawerHeader(child: Text("Header")), ListTile( title: Text("Item 1"), ), ListTile( title: Text("Item 2"), ) ], ), ),
このプログラムを実行した結果が図4です。
Drawerをプログラムからオープンする
Drawerはスワイプで表示可能ですが、プログラムで開きたい場合があります。これには、リスト4のようにします。
appBar: AppBar( // (1) Builderウィジェットを使う leading: Builder( builder: (context) => IconButton( icon: Icon(Icons.menu), onPressed: (){ // (2) Drawerを開く処理 Scaffold.of(context).openDrawer(); }) ), // ( 省略 ) ),
AppBarウィジェットでleadingプロパティには、(1)のように直接、IconButtonウィジェットを設定せずにBuilderウィジェットを設定しています。これは、onPressedメソッド内でBuildContextを利用したいためです(BuilderContextについては、後で改めます)。そして、(2)のように、openDrawerメソッドを使ってDrawerを開きます。endDrawerに設定しているDrawerを開きたい場合にはopenEndDrawerメソッドを使います。
SnackBarウィジェット
SnackBarは、画面下部にメッセージを一時的に表示するためのウィジェットです。表示したものは、時間が経過すると自動的に消えます。また、表示する位置は、behaviorプロパティにSnackBarBehaviorの値を指定することで変更できます。
また、実際に表示する場合のコードを示したものがリスト5です。
body: Center( child: TextButton( child: Text("Message"), onPressed: (){ // (1) Snackbarを表示する ScaffoldMessenger.of(context).showSnackBar( // (2) SnackBarを作成 SnackBar( // (3) 各プロパティの設定 content: Text("Hello"), behavior: SnackBarBehavior.floating, duration: Duration(seconds: 5), // (省略) ) ); }, ) ),
Snackbarを表示する際には、(1)のようにScaffoldMessengerクラスのshowSnackBarメソッドを使います。
Drawerを表示する場合には、Scaffold.ofメソッドを使いましたが、Snackbarの場合には、ScaffoldMessengerクラスを使います。これによって、Builderウィジェットを使わなくても問題なくなります。(2)でSnackBarを作ります。そして、(3)のように各プロパティを設定します。実際に設定できる項目はSnackBarを参照してください。
BottomSheetウィジェット
BottomSheetウィジェットは、図6のように画面下部により自由なUIを作りたい場合に使います。SnackBarと似ている部分もありますが、より自由なUIが作れ、メニュー表示などにも利用されます。
実際に表示する部品は、他のウィジェットのように、既定のウィジェットを使わず自由なウィジェットを利用します。
リスト6が実際のBottomSheetを表示する場合の実装例です。
onPressed: (){ // (1) 表示する処理 Scaffold.of(context).showBottomSheet((BuildContext context) { return Container( height: 100, color: Colors.amber, child: Center( child: TextButton( child: Text("Bottom Sheet"), onPressed: (){ // (2) 閉じる処理 Navigator.pop(context); }, ), ), ); }); }
実際に表示する場合には、(1)のようにshowBottomSheetメソッドを使って表示するウィジェットを作成します。また、表示したウィジェットを閉じる場合には、(2)のようにNavigator.pop()を使います。これは次回説明しますが、1つ前のページに戻る処理と同じになります。
BuilderとBuildContextとは
BuilderとBuildContextについては、これまで説明せずに使ってきました。しかし、Scaffold.ofメソッドを使ってうまく動くケースと、正しく動かないケースがあります。それは、多くの場合には指定するBuildContextが間違っているためです。BuildContextとは、ウィジェットを管理しているツリー構造の中で該当のウィジェットを管理するためのクラスで、図7のようなものをイメージしてください。
Scaffold.ofメソッドは、指定したBuildContextインスタンスを使って、親ウィジェットをたどってScaffoldウィジェットを探していく処理です。そのため、Scaffoldを作る際に使ったBuildContextを使う場合には、(1)のようになるため見つかりません。しかし、既存のウィジェットだけを使っていると、ソースコード上どこにもBuildContextが現れません。
そこで、BuilderウィジェットはBuildContextインスタンスを取得するために利用されます。これで(2)のようにScaffoldウィジェットが見つかるという仕組みです。実際にさまざまな処理を記述していくと、まったく同じコードを記述しているのに動く場合と動かない場合などがあります。その場合には今回の内容を思い出していただけると、問題解決する際にイメージしやすくなります。
まとめ
今回は、Scaffoldウィジェットで利用できるウィジェットを紹介しました。実際に作成するウィジェットも、どこに表示するかによって変わると思います。従って、今回紹介した部分のどこの部品を作るのかを考える参考にしてもらえればと思います。次回は、作成した各画面をどのように遷移させていくかのページ遷移方法を紹介していきます。