28
votes

I am a beginner in Android Development. Using android's default Navigation drawer activity I am developing an application. One of the requirements of this app is to change the background colors of layouts (including navigation drawer header color) randomly at run time.

Now everything is going fine except the color of the selected menu item on navigation drawer is still blue. like this :

enter image description here

Now what I want is as the background color of other layouts is pink the selected menu item on the navigation bar should also be pink (I mean the text color and the icon should be pink) like this :

enter image description here

Can anyone please tell how to achieve it programatically in code as I have to change selected text and icon colors at runtime randomly.

Here's the menu xml file for reference:

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


    <group android:checkableBehavior="single">
        <item
                android:id="@+id/nav_quiz_all"
                android:icon="@drawable/ic_public_black_24dp"
                android:checked="true"
                android:title="All Countries Quiz"/>
        <item
                android:id="@+id/nav_quiz_bookmarked"
                android:icon="@drawable/ic_favorite_black_24dp"
                android:title="Favorite Quiz"/>
    </group>


    <item android:title="Communicate">
        <menu>
            <item
                android:id="@+id/nav_rate"
                android:icon="@drawable/ic_star_black_24dp"
                android:title="Rate this app"/>
            <item
                android:id="@+id/nav_share"
                android:icon="@drawable/ic_share_black_24dp"
                android:title="Share"/>
            <item
                android:id="@+id/nav_feedback"
                android:icon="@drawable/ic_feedback_black_24dp"
                android:title="Feedback"/>
            <item
                android:id="@+id/nav_about"
                android:icon="@drawable/ic_info_black_24dp"
                android:title="About"/>
        </menu>
    </item>


    <item
        android:id="@+id/nav_settings"
        android:icon="@drawable/ic_settings_black_24dp"
        android:title="Settings"/>

</menu>
5

5 Answers

54
votes

First check for the NavigationView below

<android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        android:background="@color/white"
        app:itemIconTint="@drawable/drawer_item_color"
        app:itemTextColor="@drawable/drawer_item_color"
        app:headerLayout="@layout/nav_header_main"
        app:menu="@menu/activity_main_drawer" />

Check here two things

app:itemIconTint="@drawable/drawer_item_color"
app:itemTextColor="@drawable/drawer_item_color"

These both tags are using drawer_item_color.xml which is a selector in drawable folder and below is the code for it

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

use selector and add colors you want. This will do the job for you.

14
votes

First Way

try using:

app:itemIconTint="@color/color_pink"  //selected icon color
app:itemTextColor="@color/color_pink" //selected text color
app:itemBackground="@color/color_gray" 

For your NavigationView

<android.support.design.widget.NavigationView
android:id="@+id/navigation_drawer"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="@layout/header_layout"
app:itemIconTint="@color/color_pink"  
app:itemTextColor="@color/color_pink" 
app:itemBackground="@color/color_gray"
app:menu="@menu/menu_drawer" />

Second Way

For programetically change use:

navigationView.setItemTextColor(ColorStateList1);
navigationView.setItemIconTintList(ColorStateList2);

Define ColorStateList1 and ColorStateList2 as:

For Navigation View Item Text Color

int[][] state = new int[][] {
        new int[] {-android.R.attr.state_enabled}, // disabled
        new int[] {android.R.attr.state_enabled}, // enabled
        new int[] {-android.R.attr.state_checked}, // unchecked
        new int[] { android.R.attr.state_pressed}  // pressed

};

int[] color = new int[] {
        Color.WHITE,
        Color.BLUE,
        Color.WHITE,
        Color.WHITE
};

ColorStateList ColorStateList1 = new ColorStateList(state, color);

For Navigation View Item Icon Color

int[][] states = new int[][] {
        new int[] {-android.R.attr.state_enabled}, // disabled
        new int[] {android.R.attr.state_enabled}, // enabled
        new int[] {-android.R.attr.state_checked}, // unchecked
        new int[] { android.R.attr.state_pressed}  // pressed

};

int[] colors = new int[] {
        Color.WHITE,
        Color.BLUE,
        Color.WHITE,
        Color.WHITE
};

ColorStateList ColorStateList2 = new ColorStateList(states, colors);
13
votes

Firstly thank you all for responding back with your solutions :) Learning from the answers above and doing some research on ColorStateList I finally managed to create a method which sets the color of the checked item on the navigation drawer to match the color of my app theme color which is generated randomly at runtime.

Here's the method:

public void setNavMenuItemThemeColors(int color){
    //Setting default colors for menu item Text and Icon
    int navDefaultTextColor = Color.parseColor("#202020");
    int navDefaultIconColor = Color.parseColor("#737373");

    //Defining ColorStateList for menu item Text
    ColorStateList navMenuTextList = new ColorStateList(
            new int[][]{
                    new int[]{android.R.attr.state_checked},
                    new int[]{android.R.attr.state_enabled},
                    new int[]{android.R.attr.state_pressed},
                    new int[]{android.R.attr.state_focused},
                    new int[]{android.R.attr.state_pressed}
            },
            new int[] {
                    color,
                    navDefaultTextColor,
                    navDefaultTextColor,
                    navDefaultTextColor,
                    navDefaultTextColor
            }
    );

    //Defining ColorStateList for menu item Icon
    ColorStateList navMenuIconList = new ColorStateList(
            new int[][]{
                    new int[]{android.R.attr.state_checked},
                    new int[]{android.R.attr.state_enabled},
                    new int[]{android.R.attr.state_pressed},
                    new int[]{android.R.attr.state_focused},
                    new int[]{android.R.attr.state_pressed}
            },
            new int[] {
                    color,
                    navDefaultIconColor,
                    navDefaultIconColor,
                    navDefaultIconColor,
                    navDefaultIconColor
            }
    );

    mNavView.setItemTextColor(navMenuTextList);
    mNavView.setItemIconTintList(navMenuIconList);
}

you can call this method with any int color you want :)

3
votes

I have tested this code on sdk 17 to sdk 26 code write the logic after

   setContent(R.layou.your_activity)

find the navigation view with Id

 private void setupNavigationSelection(NavigationView navigationViewList) {


    /* note : warning don't use other attribute  just checked and unchecked else         wont work*/
    int[][] states = new int[][]{
            new int[]{android.R.attr.state_checked}, // checked
            new int[]{-android.R.attr.state_checked} // unchecked
    };
    int[] colors = new int[]{
            Color.RED
            Color.GREEN,
    };

    LayerDrawable layerDrawable = getSideBarDrawable(0x80dedede);
    StateListDrawable arrowImgStates = new StateListDrawable();
    Drawable normalDrawable = new ColorDrawable(Color.TRANSPARENT);;
    arrowImgStates.addState(new int[]{android.R.attr.state_pressed}, normalDrawable);
    arrowImgStates.addState(new int[]{android.R.attr.state_focused}, layerDrawable);
    arrowImgStates.addState(new int[]{android.R.attr.state_selected}, layerDrawable);
    arrowImgStates.addState(new int[]{android.R.attr.state_checked}, layerDrawable);
    arrowImgStates.addState(new int[]{}, normalDrawable);

    ColorStateList colorStateList = new ColorStateList(states, colors);
    navigationViewList.setItemTextColor(colorStateList);
    navigationViewList.setItemIconTintList(colorStateList);
    navigationViewList.setItemBackground(arrowImgStates);

}

public LayerDrawable getSideBarDrawable(int bgColor) {
    int iSize = CLViewUtil.dpToPx(6);
    GradientDrawable gradientDrawable = new GradientDrawable();
    gradientDrawable.setShape(GradientDrawable.RECTANGLE);
    gradientDrawable.setStroke(iSize, CLThemeUtil.getThemePrimaryColor(this));
    gradientDrawable.setColor(bgColor);
    LayerDrawable layerDrawable = new LayerDrawable(new Drawable[]{gradientDrawable});
    layerDrawable.setLayerInset(0, 0, -iSize, -iSize, -iSize);
    return layerDrawable;

}
1
votes

Have you tried?

mNavigationView.setItemTextColor(yourColorStateList);