Background color change in BottomNavigationView

Try this it is a sample code of navigation item select listener. hope it helps you.

 @Override
  public boolean onNavigationItemSelected(final MenuItem menuItem) {
    // update highlighted item in the navigation menu
    menuItem.setChecked(true);
    mNavItemId = menuItem.getItemId();

    // allow some time after closing the drawer before performing real navigation
    // so the user can see what is happening
    mDrawerLayout.closeDrawer(GravityCompat.START);
    mDrawerActionHandler.postDelayed(new Runnable() {
      @Override
      public void run() {
        navigate(menuItem.getItemId());
      }
    }, DRAWER_CLOSE_DELAY_MS);
    return true;
  }

Alternative solution:

Make a drawable file highlight_color.xml with following contents :

<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
     <solid android:color="YOUR HIGHLIGHT COLOR"/>
</shape>

Make another drawable file nav_item_drawable.xml with following contents:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:drawable="@drawable/highlight_color" android:state_checked="true"/>
</selector>

Finally add app:itemBackground tag in the NavView :

<android.support.design.widget.NavigationView
android:id="@+id/activity_main_navigationview"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="@layout/drawer_header"
app:itemIconTint="@color/black"
app:itemTextColor="@color/primary_text"
app:itemBackground="@drawable/nav_item_drawable"
app:menu="@menu/menu_drawer">

here the highlight_color.xml file defines a solid color drawable for the background. Later this color drawable is assigned to nav_item_drawable.xml selector.

Try this one.


found an answer from this medium post

  1. We need to use android:state_checked instead of android:state_enabled
  2. within onNavigationItemSelected you need to use return true instead of return false.

and to set background, we cannot use android:color in <item>, we need to use android:drawable

So here how it looks xml file when you are setting it for app:itemTextColor and app:itemIconTint

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

and to set app:itemBackground selector

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

Here banner_white and banner_green are pngs.


I encountered a similar problem to the OP's, but a little different. If you put sth like@color/color_selector into the BottomNavigationView's app:itemBackground="___". It will cause the view to hide in design panel, and the app to crush when launching. Though it works fine if your just set it to a constant color like @color/black.

For a more in-depth explanation, I dug into android api reference. Now I think I have found the answer that can reasonably resolve this problem. (May not accurate.)

The problem is, what you provide are NOT EXACTLY what they asked for.

app:itemIconTint and app:itemTextColor ask for a hex color, while app:itemBackground asks for a literally Drawable. The <color> elements we write in colors.xml are ColorDrawable. It's derived from Drawable so it can feed all three attributes.

However, when you change it to use a selector, things become different. Both hex color and drawable have a corresponding selector. A selector acts like the resource you put in, but the outcome is not the original one. It's more like a single-purpose wrapper. You can't feed a hex color to an attribute who requires a Drawable.

The color selector is actually a ColorStateList, provides a hex color, resides in res/color. You can use only the attribute android:color in this file. it will prompt an error if you write android:drawable.
The drawable selector is StateListDrawable, provides Drawable, resides in res/drawable. You should write android:drawable here, but there is no error if you write android:color.

However android:color only provides a hex color that can't be recognized as a Drawable, while app:itemBackground requires a Drawable, so the app is doomed. (Direct cause)

Both attribute (android:color and android:drawable) accept a ColorDrawable, here it works just like when you set a constant color.

The solution (and the practice) is:

  • Use (and only) android:drawable in a res/drawable/drawable_selector.xml. Example:

    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:drawable="@color/colorAccent" android:state_checked="true" />
        <item android:drawable="@color/colorAccentDark" />
    </selector>
    
  • Use res/color/color_selector.xml when it needs a hex color (to avoid confusing). Example:

    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:color="@android:color/white" android:state_checked="true"/>
        <item android:color="@color/colorPrimary" />
    </selector>
    
  • Provide app:itemBackground with drawable. Example:

    <android.support.design.widget.BottomNavigationView
        ...
        app:itemBackground="@drawable/drawable_selector"
        app:itemIconTint="@color/color_selector"
        app:itemTextColor="@color/color_selector"
        ... />
    

(Worth noting that if you are using Android Studio, its auto-completion feature will tell you what attributes are legal and available, and it doesn't suggest you android:color in a selector under res/drawable!)