How to programmatically change Bottom Navigation View's Icons?

10,198

Solution 1

This will change the icon and text color of a single menu item from anywhere (e.g. onResume). The code below works fine on 4.4.2 through (at least) Pie. It's bits and pieces from here and other similar threads. Some notes:

  1. The menu item's icon is a drawable called "icon", but it doesn't work quite right to simply change that like I do the text color - sometimes the icon (if any) in the xml appears instead. This seems to always work.
  2. It's written to be a static function so it's callable from multiple fragments; you could easily make it a member and strip out the activity argument in an activity class.
  3. The drawable depends on whether it's a vector or a bitmap drawable for older APIs: bit map (and new API) code is a comment; newer APIs don't need the specific vector drawable function.
    static public void setMenuItemProperties(AppCompatActivity activity,
                                             MenuItem item,
                                             int resIconDrawable, int resColor) {
        int id = item.getItemId();

        BottomNavigationItemView m = activity.findViewById(id);
        TextView t1 = m.findViewById(R.id.smallLabel);
        TextView t2 = m.findViewById(R.id.largeLabel);
        t1.setTextColor(activity.getResources().getColor(resColor));
        t2.setTextColor(activity.getResources().getColor(resColor));

        Drawable d = VectorDrawableCompat.create(activity.getResources(), resIconDrawable, null);
        //Drawable d = activity.getResources().getDrawable(resIconDrawable);
        item.setIcon(d);
    }

Call like this (from an Activity) to select between two icons and text colors for menu item 3. (navigation is the BottomNavigationView.)

      setMenuItemProperties(this, navigation.getMenu().getItem(3),
          enabled ? R.drawable.ic_settings_red_24dp : R.drawable.ic_settings_redish_24dp,
          enabled ? android.R.color.white : R.color.medium_dark_grey);

Solution 2

If you want to do it programmatically do it by setting all menu items to default icons before the switch statement.

navigation.getMenu().getItem(0).setIcon(R.drawable.defaultIcon1);
navigation.getMenu().getItem(1).setIcon(R.drawable.defaultIcon2);
navigation.getMenu().getItem(2).setIcon(R.drawable.defaultIcon3);
navigation.getMenu().getItem(3).setIcon(R.drawable.defaultIcon4);
navigation.getMenu().getItem(4).setIcon(R.drawable.defaultIcon5);
switch (menuItem.getItemId()) {
      case R.id.ic_home:
                selectedFragment = new HomeFragment();
                menuItem.setIcon(R.drawable.icon1);
                break;
      case R.id.ic_connect:
                selectedFragment = new ConnectionFragment();
                menuItem.setIcon(R.drawable.icon2);
                break;
      case R.id.ic_add:
                selectedFragment = new AddPostFragment();
                menuItem.setIcon(R.drawable.icon3);
                break;
      case R.id.ic_noti:
                selectedFragment = new NotificationFragment();
                menuItem.setIcon(R.drawable.icon4);
                break;
      case R.id.ic_profile:
                selectedFragment = new ProfileFragment();
                menuItem.setIcon(R.drawable.icon5);
                break;
}

Or You could do it by editing XML files instead of doing programmatically.

drawable/homeIconSelector.xml

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

and your menu file menu/(menunamehere).xml

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

Solution 3

Let try this approach. create an xml file in your drawable folder. For example, xml file name is home_selector.xml at drawable folder.

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

Now add home_selector in menu item of your bottom_navigation_main.xml Like: android:icon="@drawable/child_selector" Example:

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

<item
    android:id="@+id/navigation_child"
    android:icon="@drawable/child_selector"
    android:title="@string/title_child" />

</menu>

Done, Give it a try. Thank you

Share:
10,198
Kaushal
Author by

Kaushal

Updated on June 12, 2022

Comments

  • Kaushal
    Kaushal almost 2 years

    I want know how can I change Bottom Navigation View's Icons when user basically selects it and then again replace it with previous icon if user selects different option.

    enter image description here Below is my switch case snippet.

    switch (menuItem.getItemId()) {

                case R.id.ic_home:
    
                    selectedFragment = new HomeFragment();
    
                    //menuItem.setIcon(R.drawable.like_colored);
    
                    break;
    
                case R.id.ic_connect:
    
                    selectedFragment = new ConnectionFragment();
    
                    break;
    
                case R.id.ic_add:
    
                    selectedFragment = new AddPostFragment();
    
                    break;
    
                case R.id.ic_noti:
    
                    selectedFragment = new NotificationFragment();
    
                    break;
    
                case R.id.ic_profile:
    
                    selectedFragment = new ProfileFragment();
    
                    break;
    
  • Mohammad Arman
    Mohammad Arman about 3 years
    this one is helpful , when using bottom navigation view for menu item.
  • JCutting8
    JCutting8 over 2 years
    Your code is missing some formatting.