Search code examples
androidkotlinandroid-drawablebottomnavigationviewandroid-icons

Bottom Navigation view icon change not working


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


Solution

  • 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