【Android】BottomNavigationView 実装まとめメモ

このサイトを見ればMaterialの`BottomNavigationView`のすべてがわかるようにまとめました。※Material3の方は近いうちにまとめます:)
足りない部分やUI/UXデザインは随時更新していく予定です。

*\*Document*
・[ *Class -- Android Developers* ](https://developer.android.com/reference/com/google/android/material/bottomnavigation/BottomNavigationView)
・[ *Class Sourse (bottomnavigation) -- GitHub* ](https://github.com/material-components/material-components-android/blob/master/lib/java/com/google/android/material/bottomnavigation/BottomNavigationView.java)
・[ *Style Sourse (bottomnavigation) -- GitHub* ](https://github.com/material-components/material-components-android/blob/master/lib/java/com/google/android/material/bottomnavigation/res/values/styles.xml)
・[ *Attrs Sourse (navigation) -- GitHub* ](https://github.com/material-components/material-components-android/blob/master/lib/java/com/google/android/material/navigation/res/values/attrs.xml)
・[ *Attrs Sourse (bottomnavigation) -- GitHub* ](https://github.com/material-components/material-components-android/blob/master/lib/java/com/google/android/material/bottomnavigation/res/values/attrs.xml)

# 使用場面
◉　アプリに３～５つのトップレベルで表示したい画面がある場合
◉　上部Tabよりも親指で簡単に切り替えができるというメリット

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524010/11634778-31bc-4a07-9709-266eeef85845.png)



</details>

# コードまとめ

【Materialのデフォルト色】
Primary：`#6200EE`　(night：`#BB86FC`)
On Primary：`#FFFFFF`　(night：`#000000`)
Surface：`#FFFFFF`　(night：`#121212`)
On Surface：`#000000`　(night：`#FFFFFF`)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524010/39237661-0ddd-4561-3adb-55fa58351b46.png)

|   |属性１         |属性２     | 説明                      |
|:--|:-------------:|:--------:|:--------------------------|
| ❶ |Container      |―         | ―                         |
| ❷ |Navigation item|Icon      |非アクティブアイコン        |
| ❸ |Navigation item|Text Label|非アクティブテキストラベル|
| ❹ |Navigation item|Icon      |アクティブアイコン          |
| ❺ |Navigation item|Text Label|アクティブテキストラベル    |

<details><summary> 【❶Container属性】 </summary>


|要素     |属性              |関連         |デフォルト値      |説明|
|:-------:|:----------------:|:----------:|:----------------:|:---|
|Color    |`app:backgroundTint`|N/A         |`?attr/colorSurface`|`#FFFFFF`　(night：`#121212`)    |
|Elevation|`app:elevation`     |`setElevation`|8dp               | 値が大きいほど影が大きくなる |

</details>

<details><summary> 【❷～❺Navigation item属性】 </summary>

|要素                |属性                    |関連                                         |デフォルト値                          |説明|
|:------------------:|:----------------------:|:------------------------------------------:|:------------------------------------:|:---|
|Menuresource        |`app:menu`                |`inflateMenu`,<br>`getMenu`                         |N/A                                   |アイテムを設定    |
|Ripple(非アクティブ)|`app:itemRippleColor`     |`setItemRippleColor`,<br>`getItemRippleColor`        |`?attr/colorOnSurface`at 8%(seeallstates)|`#000000`　(night：`#FFFFFF`) の薄い色   |
|Ripple(アクティブ)  |－                      |－                                           |`?attr/colorPrimary`at 8%(seeallstates)  | `#6200EE`　(night：`#BB86FC`) の薄い色  |
|Labelvisibilitymode |`app:labelVisibilityMode`|`setLabelVisibilityMode`,<br>`getLabelVisibilityMode`|`LABEL_VISIBILITY_AUTO`                 | 下に記載   |

:::note info
`LABEL_VISIBILITY_AUTO`(デフォルト)
　項目が 3 つ以下の場合、ラベルは「LABEL_VISIBILITY_LABELED」として動作し、項目が 4 つ以上の場合は「LABEL_VISIBILITY_SELECTED」として動作する。
`LABEL_VISIBILITY_SELECTED`
　ラベルは選択したナビゲーション項目にのみ表示さる。
`LABEL_VISIBILITY_LABELED`
　ラベルはすべてのナビゲーション項目に表示される。
`LABEL_VISIBILITY_UNLABELED`
　すべてのナビゲーション項目のラベルが非表示になる。
:::

</details>

<details><summary> 【❷❹Icon属性】 </summary>

|要素                |属性                               |関連                                               |デフォルト値                |説明|
|:------------------:|:---------------------------------:|:------------------------------------------------:|:--------------------------:|:---|
|Icon                |`android:icon`in the menu resource|N/A                                               |N/A                         |メニューリソースファイルの中でアイコンを設定    |
|Size                |`app:itemIconSize`                   |`setItemIconSize`,<br>`setItemIconSizeRes`,<br>`getItemIconSize`|24dp                        |アイコンのサイズ(1:1)    |
|Color (非アクティブ)|`app:itemIconTint`                    |`setItemIconTintList`,<br>`getItemIconTintList`           |`?attr/colorOnSurface` at 60%|`#000000`　(night：`#FFFFFF`)のやや薄い色    |
|Color (アクティブ)  |―                                   |―                                                 |`?attr/colorPrimary`         |`#6200EE`　(night：`#BB86FC`)    |

</details>

<details><summary> 【❸❺Text Label属性】 </summary>

|要素                     |属性                          |関連                                                       |デフォルト値               |説明|
|:-----------------------:|:----------------------------:|:---------------------------------------------------------:|:------------------------:|:---|
|Text label               |`android:title` in the menu resource|N/A                                                  |N/A                       | メニューリソースファイルの中でテキストを設定  |
|Color (非アクティブ)     |`app:itemTextColor`             |`setItemTextColor`,<br>`getItemTextColor`                          |`?attr/colorOnSurface` at 60%|`#000000`　(night：`#FFFFFF`)のやや薄い色   |
|Color (アクティブ)       |―                             |―                                                          |`?attr/colorPrimary`         | `#6200EE`　(night：`#BB86FC`)  |
|Typography (非アクティブ)|`app:itemTextAppearanceInactive`|`setItemTextAppearanceInactive`,<br>`getItemTextAppearanceInactive`|`?attr/textAppearanceCaption`|textAppearanceCaptionの[Materialのデフォルト値](https://m2.material.io/develop/android/theming/typography)は`Regular 12sp`   |
|Typography (アクティブ)  |`app:itemTextAppearanceActive`  |`setItemTextAppearanceActive`,<br>`getItemTextAppearanceActive`    |`?attr/textAppearanceCaption`| 上に同じ  |

</details>

# レイアウト
## 1. 基礎コード
```activity_main.xml
    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottom_navigation"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:menu="@menu/bottom_navigation_menu"/>
```
`app:menu`ではアイテムの設定を行う。メニューリソースファイルにアイテムを書いてそのファイルを指定する。

```res/menu/bottom_navigation_menu.xml
    <menu xmlns:android="http://schemas.android.com/apk/res/android">
          <item
              android:id="@+id/page_1"
              android:enabled="true"
              android:icon="@drawable/icon_1"
              android:title="@string/text_label_1"/>
          <item
              android:id="@+id/page_2"
              android:enabled="true"
              android:icon="@drawable/icon_2"
              android:title="@string/text_label_2"/>
              ：
    </menu>
```

:::note info
アイテムの数は３～５つが適切な数
:::

## 2. スタイルの設定
スタイルは大きく２つのスタイルがあり、３つ目は２つを状態によって切り替えるスタイル

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524010/b450c1ed-cb7d-ed17-2c87-4e7ad4939255.png)


|要素     |スタイル  |Containerの色 |NavigationItemの色(非アクティブ)|NavigationItemの色(アクティブ) |
|:------:|:--------:|:------------:|:-----------------------------:|:-----------------------------:|
|Default style|`Widget.MaterialComponents.BottomNavigationView`|`?attr/colorSurface` `#FFFFFF`　(night：`#121212`)|`?attr/colorOnSurface` at 60% `#000000`　(night：`#FFFFFF`)のやや薄い色|`?attr/colorPrimary` `#6200EE`　(night：`#BB86FC`)|
|Colored style|`Widget.MaterialComponents.BottomNavigationView.Colored`|`?attr/colorPrimary` `#6200EE`　(night：`#BB86FC`)|`?attr/colorOnPrimary` at 60% `#FFFFFF`　(night：`#000000`)のやや薄い色|`?attr/colorOnPrimary` `#FFFFFF`　(night：`#000000`)|
|Dark theme supported style|`Widget.MaterialComponents.BottomNavigationView.PrimarySurface`|`?attr/colorPrimary` in light theme `#6200EE`,<br>`?attr/colorSurface` in dark theme (night：`#121212`)|`?attr/colorOnPrimary` at 60% in light theme  `#FFFFFF`のやや薄い色,<br>`?attr/colorOnSurface` at 60% in dark theme (night：`#FFFFFF`)|`?attr/colorOnPrimary` in light theme `#FFFFFF`,<br>`?attr/colorPrimary` in dark theme (night：`#BB86FC`)|

:::note warn
Widget.MaterialComponents.BottomNavigationView.PrimarySurface スタイルは、ライトテーマとダークテーマの間で自動的に切り替わる。
:::

デフォルトからスタイルを上のどれかに変えたいときは`style`をどれか１つ設定する。

```activity_main.xml
    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottom_navigation"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        
        style="@style/Widget.MaterialComponents.BottomNavigationView"
        style="@style/Widget.MaterialComponents.BottomNavigationView.Colored"
        style="@style/Widget.MaterialComponents.BottomNavigationView..PrimarySurface"
        
        app:menu="@menu/bottom_navigation_menu"/>
```

:::note info
デフォルトのスタイル属性: `?attr/bottomNavigationStyle`
:::

## 3. 色の変更
色は基本的にアプリに設定している `?attr/colorPrimary` 、`?attr/colorOnPrimary` 、`?attr/colorSurface` 、`?attr/colorOnSurface` で配色される。
もし、このアプリの基本の色を変えずに`BottomNavigation`のみ色を変えたい場合は２つの方法がある。

### 初心者向けの色変更方法
1つ目は、コードまとめ(↑) の色に関係する部分をXMLに追加するという方法。
`style`を使わないので初心者にわかりやすい書き方なはず。

```activity_main.xml
    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottom_navigation"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        
        app:itemRippleColor="@color/orange_500"
        app:itemTextColor="@color/green_500"
        app:itemIconTint="@color/yellow_500"
        app:backgroundTint="@color/pink_700"
        
        app:menu="@menu/bottom_navigation_menu"/>
```

::: note info
　自分でカスタマイズするときは、マテリアルデザインを心がけよう!（[このサイトが詳しく解説](https://uxplanet.org/how-to-design-a-better-bottom-navbar-5127c8b8102f)してるぞっ！）
:::

ただし、この方法には
1. ダークテーマなど他のテーマを実装するときに不便
1. マテリアルデザインが崩れる
1. 個々に設定するのめんどくさい　　　　　などのデメリットも多い...。

### 【オススメ】 色変更方法
そこで、`style`でカスタマイズする方法が一番オススメ。

```activity_main.xml
    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottom_navigation"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        
        style="?attr/bottomNavigationStyle"
        
        app:menu="@menu/bottom_navigation_menu"/>
```

```res/values/themes.xml
<style name="Theme.App" parent="Theme.MaterialComponents.DayNight.NoActionBar">
    ：

    <item name="bottomNavigationStyle">@style/Widget.App.BottomNavigationView</item>
    
</style>
```


```res/values/styles.xml
<style name="Widget.App.BottomNavigationView" parent="Widget.MaterialComponents.BottomNavigationView.PrimarySurface">
    <item name="materialThemeOverlay">@style/ThemeOverlay.App.BottomNavigationView</item>
</style>

<style name="ThemeOverlay.App.BottomNavigationView" parent="">
    <item name="colorPrimary">@color/citron_400</item>
    <item name="colorOnPrimary">@color/citron_900</item>
    <item name="colorSurface">@color/citron_100</item>
    <item name="colorOnSurface">@color/citron_900</item>
</style>
```

# JAVAコード
👇選択を受け取るリスナー
```MainActivity.java
BottomNavigationView bottomNavigationView = findViewById(R.id.bottom_navigation);

bottomNavigationView.setOnItemSelectedListener(new NavigationBarView.OnItemSelectedListener() {
    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem item) {
        switch (item.getItemId()){
            case R.id.page_1:
                //page_1のアイテムが選択されたときの処理
                break;
            case R.id.page_2:
                //page_2のアイテムが選択されたときの処理
                break;
            default:
                break;
        }
        return true;
    }
});
```

👇便利な処理
```MainActivity.java
    //アイテムの選択を動的にする
    bottomNavigationView.setSelectedItemId(R.id.page_2);

```


# UI/UXデザイン
おしゃれなデザインを作るには`外部ライブラリ`を探して実装する
### chip-navigation-bar

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524010/89bbe643-c005-1881-7ecd-402e26b98080.png)
・[ *Source Code -- (GitHub)* ](https://github.com/ismaeldivita/chip-navigation-bar)
・[ *Explanation -- (YouTube)* ](https://www.youtube.com/watch?v=zWDdaejNj0o)



### MeowBottomNavigation
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524010/1a7dacdc-0168-9adf-315c-8e3573fa9b2c.png)
・[ *Source Code -- (GitHub)* ](https://github.com/oneHamidreza/MeowBottomNavigation)
・[ *Explanation -- (YouTube)* ](https://www.youtube.com/watch?v=fmrYeiw-0EQ)




# おわりに
見落としなどあるかもしれません。
`BottomNavigationView` 関連また使う機会あったら更新します。

(Links)
▶ https://m2.material.io/components/bottom-navigation/android