アプリを開発していると、画像のようにページ下部に画面遷移用のナビゲーションバーを実装したい時がある。
Flutterではこのような機能を、Scaffold
ウィジェットのBottomNavigationBar
を利用することで簡単に実装できる。
本エントリではBottomNavigationBar
の基本的な使い方、動作フロー、実際のアプリをベースに説明をする。
BottomNavigationBarとは
BottomNavigationBar
はmaterialデザインで使用されるページ下部に表示される画面切り替え用のナビゲーションバー用ウィジェット。
BottomNavigationBar
を使用する際に必要になることが多いプロパティを説明する。
プロパティ
items ※必須
BottomNavigationBar
上に表示される各アイテム。
このアイテムをタップすることで表示を切り替える。
List<BottomNavigationBarItem>
型のリストを渡す。
またアイテム数は2以上が必要。
currentIndex
現在選択されているアイテムのインデックスを指定する。 この値を変更しないと、再ビルドしても表示が切り替わらないので注意。
int
型を渡す。インデックスは0から始まり、左から1ずつ増える。
onTap
アイテムをタップされた際にコールされるイベントハンドラ。 引数にはタップされたアイテムのインデックスが渡される。
BottomNavigationBarの動作フロー
一般的には次のようなフローで動作する。
- ウィジェットがビルドされる。この時
currentIndex
が読み取られ、インデックスに該当するitems
のアイテムにフォーカスが当たる - ユーザーがアイテムをタップする
onTap
に渡されているハンドラメソッドがコールされる。- ハンドラメソッド内で
setState()
がコールされてcurrentIndex
が更新される - 再ビルドされてフォーカスの当たるアイテムが変わる
次に実際にアプリのコードに沿って動作を説明する。
作成アプリ
次のgif画像のアプリを作成する。
仕様
bottomNavigationBar
に表示されている項目を選択することでメインコンテンツを切り替える。
ソースコード
import 'package:flutter/material.dart'; // 1 void main() { runApp(const MyApp()); } // 2 class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( title: 'test app', theme: ThemeData( primarySwatch: Colors.blue, ), home: HomeWidget()); } } // 3 class HomeWidget extends StatefulWidget { const HomeWidget({Key? key}) : super(key: key); @override State<HomeWidget> createState() => _HomeWidgetState(); } // 4 class _HomeWidgetState extends State<HomeWidget> { // 5 List<Widget> pages = [ Container( color: Colors.red, ), Container( color: Colors.green, ), Container( color: Colors.blue, ), ]; // 6 List<BottomNavigationBarItem> items = [ BottomNavigationBarItem(icon: Icon(Icons.home), label: "home"), BottomNavigationBarItem(icon: Icon(Icons.person), label: "user"), BottomNavigationBarItem(icon: Icon(Icons.settings), label: "setting"), ]; // 7 int _selectedItemIndex = 0; // 8 void updateSelectedItemIndex(newItemIndex) { setState(() { _selectedItemIndex = newItemIndex; }); } // 9 @override Widget build(BuildContext context) { // 10 return Scaffold( // 11 body: pages[_selectedItemIndex], // 12 bottomNavigationBar: BottomNavigationBar( // 13 currentIndex: _selectedItemIndex, // 14 onTap: updateSelectedItemIndex, // 15 items: items), ); } }
上のコードについて番号ごとに説明していく。
1 Flutterアプリのエントリーポイント
2
ウィジェットツリーのルートウィジェット。
ここでMaterialApp
をビルドする。
3
StatefulWidget
を継承したHomeWidget
。
このウィジェットでUIを作成する。
4
HomeWidget
のState
インスタンス。
5 実際にコンテンツ部分に表示するウィジェットのリスト。 コンテンツが切り替わったことがわかりやすいように、それぞれ背景色を変えている。
6
BottomNavigationBarItem
のリスト。
7
現在選択されているBottomNavigationBarItem
の番号。
リストのインデックスと同様に0から始まり1ずつ増える。
8
BottomNavigationBarItem
がタップされた際にコールされるイベントハンドラメソッド。
setState()
をコールして選択されているBottomNavigationBarItem
が切り替わったことを
Flutterフレームワークに伝える。
9
HomeWidget
のState
インスタンスのビルドメソッド。
ここにUIとして表示したいウィジェットを記述する。
10
Scaffold
ウィジェットをビルドする。
11
Scaffold
ウィジェットのbody
にはpages
を渡す。
この時のインデックスは_selectedItemIndex
を渡し、選択されたインデックスに対応するコンテンツを表示する。
12
Scaffold
のbottomNavigationBar
にBottomNavigationBar
ウィジェットを渡す。
13
現在選択されているbottomNavigationBarItem
のインデックス。
_selectedItemIndex
を渡すことでsetState()
がコールされて再ビルドが生じた際に
現在選択されているインデックスを更新できる。
14
BottomNavigationBarItem
がタップされた際にコールされるイベントハンドラメソッド。
updateSelectedItemIndex
を渡す。この時引数の形式を揃える必要がある。
15
BottomNavigationBar
ウィジェット部分に表示される各アイテム。
6で説明したitems
リストを渡す。