前人未踏の領域へ Androidアプリ開発編

Androidアプリ開発に関する調査メモ置き場。古い記事にはアプリ以外も含まれます。

Android:BottomNavigationViewに独自の画像をセットする

課題

マテリアルコンポーネントのBottomNavigationViewを使いたいが、一部のアイコンだけログインユーザーの画像にしたところ、すべてのタブに自動的にColorListが適用されてしまい画像が表示されない。どうすればよいか。

対応

BottomNavigationViewはタブの選択・非選択時に色を変えるために itemIconTintitemTextColor という属性を持っている。しかし、これが有効になっていると問答無用ですべてのタブに適用されてしまうので無効化する必要がある。

itemIconTintの無効化
// アプリでアイコンを制御する
val bottomNavigation: BottomNavigationView = binding.main.bottomNavigation
bottomNavigation.itemIconTintList = null

style.xmlitemIconTint@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を使い分ければタブが選択されたタイミングで画像を差し替えたり色を足したりなんてこともできる。