4

I want to change to icons of the bottom navigation view as we switch items.

enter image description here

I have light blue icons and dark blue icons for selected items. I am using selector drawable for each navigation item but I see the images like below in grey as inactive and blue as active

enter image description here

Here is my code

bottom_nav_menu

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:id="@+id/navigation_home"
        android:icon="@drawable/home_icon_selector"
        android:title="@string/title_home" />

    <item
        android:id="@+id/navigation_scheduler"
        android:icon="@drawable/schelduler_icon_selector"
        android:title="@string/title_scheduler" />

    <item
        android:id="@+id/navigation_favourites"
        android:icon="@drawable/favourites_icon_selector"
        android:title="@string/title_favourites" />


    <item
        android:id="@+id/navigation_settings"
        android:icon="@drawable/settings_icon_selector"
        android:title="@string/title_settings" />
</menu>

home

<com.google.android.material.bottomnavigation.BottomNavigationView
    android:id="@+id/nav_view"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginStart="@dimen/margin_20"
    android:layout_marginLeft="@dimen/margin_20"
    android:layout_marginRight="@dimen/margin_20"
    android:layout_marginEnd="@dimen/margin_20"
    android:layout_marginBottom="@dimen/margin_8"
    android:background="@drawable/bottom_navigation_background"
    android:elevation="8dp"
    app:itemIconTint="@drawable/bottom_navigation_color_selector"
    app:labelVisibilityMode="unlabeled"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:menu="@menu/bottom_nav_menu" />

And selectors

scheduler selector

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/qa_scheduler_inactive" android:state_checked="false"/>
    <item android:drawable="@drawable/ic_scheduler_blue" android:state_checked="true"/>
</selector>

Settings selector

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/qa_settings_inactive" android:state_checked="false"/>
    <item android:drawable="@drawable/ic_settings_blue" android:state_checked="true"/>
</selector>

Favorites selector

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/qa_favorites_inactive" android:state_checked="false"/>
    <item android:drawable="@drawable/ic_favourites_blue" android:state_checked="true"/>
</selector>

Home Selector

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/qa_home_inactive" android:state_checked="false"/>
    <item android:drawable="@drawable/ic_home" android:state_checked="true"/>
</selector>

Activity code

    val navView: BottomNavigationView = findViewById(R.id.nav_view)
    val navController = findNavController(R.id.nav_host_fragment)
    // Passing each menu ID as a set of Ids because each
    // menu should be considered as top level destinations.
    val appBarConfiguration = AppBarConfiguration(setOf(
            R.id.navigation_home, R.id.navigation_scheduler, R.id.navigation_favourites, R.id.navigation_settings))
    //  setupActionBarWithNavController(navController, appBarConfiguration)
    navView.setupWithNavController(navController)

What am I doing wrong here? Please help...

Edit : I am using following drawables

enter link description here

enter link description here

Zain
  • 37,492
  • 7
  • 60
  • 84
Sid
  • 2,792
  • 9
  • 55
  • 111

3 Answers3

5

The reason of this issue is that there is always a value for app:itemIconTint, even if it is not used, it takes the default values of the primary/accent colors.

So to solve your problem you need to explicitly disable this with:

val btmNav = findViewById<BottomNavigationView>(R.id.nav_view)
navView.itemIconTintList = null

Although I do recommend another thing:

The icons are already the same icons in checked/unchecked states, but with different tint colors. If these icons are vectors, then you can just tint colors using a selector in app:itemIconTint, and use a single version of the icon without needing to duplicate the resources:

icon_color_selector.xml:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="#2596CD" android:state_checked="true" />
    <item android:color="#84D0F4" android:state_checked="false" />
</selector>

And apply that:

<com.google.android.material.bottomnavigation.BottomNavigationView
    ...
    app:itemIconTint="@drawable/icon_color_selector"

And keep the menu items only with icons not the selectors, for instance:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:id="@+id/navigation_home"
        android:icon="@drawable/home_icon"  //<<<<< icon not selector
        android:title="@string/title_home" />

    ....

</menu>

UPDATE:

As you are using navigation architecture components, make sure to have the same ids in the bottomNavView menu that matches the corresponding ones in the navGraph of the bottomNavView fragments.

In case you don't use a navGraph for the bottomNavView fragments, then you can't use navView.setupWithNavController(navController)

Here is with your drawable icon

Zain
  • 37,492
  • 7
  • 60
  • 84
  • but I dont want to change just color of icon. the icons are different for selected and default one. – Sid Aug 25 '21 at 14:23
  • @Sid Then you can go for `btmNav.itemIconTintList = null` – Zain Aug 25 '21 at 14:25
  • I tried but after that the default icon is set right which I wanted but for selected icon it shows white. – Sid Aug 25 '21 at 14:33
  • @Sid Which type of icons do you use .. Are they XML drawables? I still couldn't reproduce the issue.. Please check the gif in the answer – Zain Aug 25 '21 at 17:26
  • please check edited question given link for one of the drawbles used for selected and default. @Zain – Sid Aug 26 '21 at 12:46
  • @Sid Please check updated answer, hopefully your issue can be resolved now – Zain Aug 26 '21 at 21:41
  • @Sid Any thoughts upon this update.. I am willing to help further if you still encounter issues – Zain Aug 28 '21 at 13:19
  • hi sorry could not work for 2 days.. I did not get the answer shall I not use navView.setupWithNavController(navController)? then how bottom navigation will work with fragments? – Sid Sep 01 '21 at 09:59
  • No you should use `navView.setupWithNavController(navController)` in case the individual fragments of the `BottomNavView` are managed by a navigation graph. – Zain Sep 01 '21 at 21:53
  • Yes then I am using same. – Sid Sep 03 '21 at 09:48
  • My fragments are in navigation graph and that is passed to bottomNavView as navgraph. still Not getting the icons I want to show. How u did in that video? – Sid Sep 03 '21 at 09:54
  • I have no special code other than that shared..I think there is something probably in theme that makes yours didn't work.. can you share a demo so that i can figure it out – Zain Sep 03 '21 at 10:54
0

This is just a wild guess, but maybe this line here:

app:itemIconTint="@drawable/bottom_navigation_color_selector"

is interfering with the colors of your drawables? If your drawables have the right colors (light blue/dark blue) they should work with your current selectors.

Alternatively, check that you don't set app:itemIconTint for the bottom-nav some other way, eg through a theme or programmatically!

  • I tried removed that line so now its all icons showing in grey color and selected to white – Sid Aug 24 '21 at 10:06
0

You can achieve this using using selector like @Chris said or you can do it dynamically by using setOnNavigationItemSelectedListener{}

update - For changing icons , you can just brute force by changing the current item.icon to filled and others to unfilled icon , see here to get a gist of it (don't copy its for tabLayout).

navView.setOnNavigationItemSelectedListener { item -> 
            // change  the icon to filled icon
            true
        }

It seems so that listner is depreciated so refer this

Anshul
  • 1,495
  • 9
  • 17