FlutterでBottomNavigationBarを実装する

# BottomNavigationBar
## 動き
![g01t6JMX1q.gif](https://qiita-image-store.s3.amazonaws.com/0/122320/45ca2a98-4586-a0e2-65e6-ffe3c45e10be.gif)

## 主要な登場人物
- Scaffold
- PageView
- PageController
- BottomNavigationBar
- BottomNavigationBarItem
- 現在表示しているページの番号(画面用のWidgetのメンバ変数_pageとする)

## 実装
### Scaffold
#### 役割
表示したい画面を作成する
#### 準備
1. 画面用のWidgetのbuild関数の戻り値としてScaffoldを作成する(それ以外の場合もあるのかもしれない？)

```dart
class _MyHomePageState extends State<MyHomePage> {
...
  @override
  Widget build(BuildContext context) {
    // 1
    return new Scaffold(
```

### PageController
#### 役割
表示するページの遷移を担当する
#### 準備
1. 画面用のWidgetにメンバ変数として用意する
2. 画面用のWidgetのinitState/disposeにて、作成とdisposeを呼ぶ
3. (PageViewのcontrollerにメンバに渡す) = PageView準備:2

```dart
class _MyHomePageState extends State<MyHomePage> {
  // 1
  PageController _pageController;
  int _page = 0;

  @override
  void initState() {
    super.initState();
    // 2
    _pageController = new PageController();
  }

  @override
  void dispose() {
    super.dispose();
    // 2
    _pageController.dispose();
  }

```

### PageView
#### 役割
ページの見た目(BottomNavigationBarのアイコンをタップした際に切り替わるページ部分)
#### 準備
1. ScaffoldのbodyにPageViewを作成する
2. PageViewのcontrollerにメンバ変数で持っているPageControllerを渡す
3. PageViewのonPageChangedにsetStateを書いて、現在表示しているページの番号(_page)を保持する
4. PageViewのchildrenに配列で適当なWidgetを作成する

```dart
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
...
      // 1
      body: new PageView(
        // 2
        controller: _pageController,
        // 3
        onPageChanged: onPageChanged,
        // 4
        children: [
          new HomePage(),      // StatefulWidgetを別クラスに書き出している![g01t6JMX1q.gif](https://qiita-image-store.s3.amazonaws.com/0/122320/ce1eafb4-5ba1-44c4-bfd8-f75ef99eb673.gif)

          new SettingsPage(),  // けど、Container作るとかでも大丈夫
        ],
      ),

...
  // 3（関数に分けなくても良い）
  void onPageChanged(int page) {
    setState(() {
      this._page = page;
    });
  }
```

### BottomNavigationBar
#### 準備
1. ScaffoldのbottomNavigationBarにBottomNavigationBarを作成する
2. BottomNavigationBarのitemsに配列でBottomNavigationBarItemを渡す
3. BottomNavigationBarのonTapにPageControllerの~ToPageを実装する(当記事ではanimateToPageを使用している)
4. BottomNavigationBarのcurrentIndexに現在表示しているページの番号(_page)を渡す

```dart

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
...
      // 1
      bottomNavigationBar: new BottomNavigationBar(
        // 4
        currentIndex: _page,
        // 3
        onTap: onTapBottomNavigation,
        // 2
        items: [
          new BottomNavigationBarItem(
              icon: new Icon(Icons.home),
              title: new Text("Home")
          ),
          new BottomNavigationBarItem(
              icon: new Icon(Icons.settings),
              title: new Text("Setting")
          ),
        ],
      ),

...
  // 3(関数に分けなくても良い)
  void onTapBottomNavigation(int page) {
    _pageController.animateToPage(
        page,
        duration: const Duration(milliseconds: 300),
        curve: Curves.ease
    );
  }
```

<details><summary>コード全文</summary><div>

```dart
class _MyHomePageState extends State<MyHomePage> {
  PageController _pageController;
  int _page = 0;

  @override
  void initState() {
    super.initState();
    _pageController = new PageController();
  }

  @override
  void dispose() {
    super.dispose();
    _pageController.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('Application Name'),
        elevation: 4.0,
      ),
      body: new PageView(
        controller: _pageController,
        onPageChanged: onPageChanged,
        children: [
          new HomePage(),
          new SettingsPage(),
        ],
      ),
      bottomNavigationBar: new BottomNavigationBar(
        currentIndex: _page,
        onTap: onTapBottomNavigation,
        items: [
          new BottomNavigationBarItem(
              icon: new Icon(Icons.home),
              title: new Text("Home")
          ),
          new BottomNavigationBarItem(
              icon: new Icon(Icons.settings),
              title: new Text("Setting")
          ),
        ],
      ),
    );
  }

  void onTapBottomNavigation(int page) {
    _pageController.animateToPage(
        page,
        duration: const Duration(milliseconds: 300),
        curve: Curves.ease
    );
  }

  void onPageChanged(int page) {
    setState(() {
      this._page = page;
    });
  }
}
```
</div></details>

## 参照
- https://github.com/flutter/flutter/blob/master/examples/flutter_gallery/lib/demo/material/bottom_navigation_demo.dart
- https://github.com/fablue/building-a-social-network-with-flutter