課題
マテリアルコンポーネントのBottomNavigationViewを使いたいが、一部のアイコンだけログインユーザーの画像にしたところ、すべてのタブに自動的にColorListが適用されてしまい画像が表示されない。どうすればよいか。
対応
BottomNavigationViewはタブの選択・非選択時に色を変えるために itemIconTint
と itemTextColor
という属性を持っている。しかし、これが有効になっていると問答無用ですべてのタブに適用されてしまうので無効化する必要がある。
itemIconTintの無効化
// アプリでアイコンを制御する val bottomNavigation: BottomNavigationView = binding.main.bottomNavigation bottomNavigation.itemIconTintList = null
style.xmlでitemIconTint
に@null
をセットしても効果がないので注意。
アイコンの切り替え
BottomNavigationView.menu.getItem(index)で該当位置のタブのアイコンが取得できる。そこにsetIconで画像をセットする。
// ユーザータブには画像をセットする val userImage = getUserImage() val userTabIndex = 3 val userTab = bottomNavigation.menu.getItem(userTabIndex) userTab.icon = userImage
BottomNavigationの設定関数としてはこんな感じ
private fun setupBottomNavigation() { val navHostFragment = supportFragmentManager.findFragmentById( R.id.nav_host_fragment ) as NavHostFragment navController = navHostFragment.navController // BottomNavigationとnavControllerを紐付け binding.main.bottomNavigation.setupWithNavController(navController) // アプリでアイコンを制御する binding.main.bottomNavigation.itemIconTintList = null // ユーザータブには画像をセットする val userImage = getUserImage() val userTabIndex = 3 val userTab = binding.main.bottomNavigation.menu.getItem(userTabIndex) userTab.icon = userImage // タブが選択された navController.addOnDestinationChangedListener { _, destination, _ -> // 省略 } // タブが再選択された binding.main.bottomNavigation.setOnItemReselectedListener { // 省略 } }
備考
画像にはLayerDrawableやStateListDrawableもセットできるので、それらの中にstate_checked
のON/OFFを使い分ければタブが選択されたタイミングで画像を差し替えたり色を足したりなんてこともできる。