216

Can I change the background color of a Menu item in Android?

Please let me know if anyone have any solution to this. The last option will be obviously to customize it but is there any way for changing the text color without customizing it.

Alex Rashkov
  • 9,833
  • 3
  • 32
  • 58
sunil
  • 9,541
  • 18
  • 66
  • 88

29 Answers29

378

One simple line in your theme :)

<item name="android:actionMenuTextColor">@color/your_color</item>
Muhammad Alfaifi
  • 5,662
  • 2
  • 19
  • 23
  • 26
    NOTE: This MUST go in the main Theme definition for your app, NOT within the `actionBarStyle` for example. It won't work within `actionBarStyle`, even though that seems logical! – Colin M. Sep 24 '14 at 18:31
  • 50
    To support lower API versions use `@color/your_color` don't use the Android namespace – alex.p Jul 08 '15 at 14:08
  • 7
    @ColinM. It has to go into _a_ theme. If you set a `theme` attribute on your toolbar, this works. – DariusL Sep 30 '15 at 10:04
  • 2
    Was not working for me either with or without android: namespace. It was added to the main app theme. – racs Jun 04 '17 at 23:53
  • 5
    I am still completely unable to change the text color. My overall theme textcolor just takes preference. Any help? None of these answers work. – David P Jun 21 '17 at 07:26
  • 12
    Doesn't seem to work with `Theme.MaterialComponents.DayNight` – behelit Jun 01 '19 at 02:59
  • This only change the text on the right of the toolbar but not the menu itself, the menu keeps being white by default, any other idea – Pxaml Jul 23 '19 at 13:18
137

It seems that an

  <item name="android:itemTextAppearance">@style/myCustomMenuTextAppearance</item>

in my theme and

   <style name="myCustomMenuTextAppearance" parent="@android:style/TextAppearance.Widget.IconMenu.Item">
        <item name="android:textColor">@android:color/primary_text_dark</item>
    </style>

in styles.xml change the style of list-items but not menu items.

Mladen Rakonjac
  • 9,562
  • 7
  • 42
  • 55
Marcus Wolschon
  • 2,550
  • 2
  • 22
  • 28
  • 5
    This works great for context menu items (not menu items from the menu button) which is what I've been looking for. Much simpler than the whole LayoutFactory mess. – chubbsondubs Jun 06 '12 at 16:40
  • The `android:itemTextAppearance` attribute cannot be placed within a style whose parent is `parent="@android:style/Widget.Holo.ListPopupWindow"` since that will not render properly. It must be in a top level style like one whose parent is `android:Theme.Holo.Light.DarkActionBar`. – Etienne Lawlor Jun 22 '13 at 08:31
  • Where should I add @style/myCustomMenuTextApearance ? – Bagusflyer Feb 19 '14 at 09:28
  • @bagusflyer you should add that in the root style of your theme, i.e. the style that is a child of `Theme.Holo` or `Theme.Holo.Light.DarkActionBar` or similar. – Tash Pemhiwa Jun 12 '14 at 14:10
  • 1
    This works great in "Theme.MaterialComponents.DayNight.NoActionBar" – CodeFluid Jun 26 '22 at 23:50
111

You can change the color of the MenuItem text easily by using SpannableString instead of String.

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.your_menu, menu);

    int positionOfMenuItem = 0; // or whatever...
    MenuItem item = menu.getItem(positionOfMenuItem);
    SpannableString s = new SpannableString("My red MenuItem");
    s.setSpan(new ForegroundColorSpan(Color.RED), 0, s.length(), 0);
    item.setTitle(s);
}
Habizzle
  • 2,971
  • 3
  • 20
  • 23
  • 11
    This worked for me in both 4.4 and 5+ using ```menu.findItem(R.id.menu_item_id);``` instead of ```menu.getItem()``` – haagmm Dec 21 '15 at 22:01
  • 1
    Worked for me too [using findItem(...)]. – dazed Jan 21 '16 at 11:20
  • 7
    solutions work only for item in overflow....i wan't to change the item colour which is visible by setting showAsAction:"always" – Junaid Jul 22 '16 at 13:54
78

If you are using the new Toolbar, with the theme Theme.AppCompat.Light.NoActionBar, you can style it in the following way.

 <style name="ToolbarTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="android:textColorPrimary">@color/my_color1</item>
    <item name="android:textColorSecondary">@color/my_color2</item>
    <item name="android:textColor">@color/my_color3</item>
 </style>`

According to the results I got,
android:textColorPrimary is the text color displaying the name of your activity, which is the primary text of the toolbar.

android:textColorSecondary is the text color for subtitle and more options (3 dot) button. (Yes, it changed its color according to this property!)

android:textColor is the color for all other text including the menu.

Finally set the theme to the Toolbar

<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    app:theme="@style/ToolbarTheme"
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:minHeight="?attr/actionBarSize"/>
Gabriella Angelova
  • 2,985
  • 1
  • 17
  • 30
Sudara
  • 4,769
  • 3
  • 34
  • 39
  • Which item governs the text on the buttons that are shown as actions (text) on the toolbar? Neither android:textColorPrimary, android:textColorSecondary, nor android:textColor seem to affect them. – LarsH May 31 '17 at 01:16
  • In answer to my question in the preceding comment: `android:actionMenuTextColor` (see https://stackoverflow.com/a/5538709/423105). – LarsH May 31 '17 at 01:23
  • Until I read your answer, I was going crazy trying to change the color of the 3 dots! – Carl Smith Feb 03 '21 at 10:20
43

I went about it programmatically like this:

public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.changeip_card_menu, menu); 
    for(int i = 0; i < menu.size(); i++) {
        MenuItem item = menu.getItem(i);
        SpannableString spanString = new SpannableString(menu.getItem(i).getTitle().toString());
        spanString.setSpan(new ForegroundColorSpan(Color.BLACK), 0,     spanString.length(), 0); //fix the color to white
        item.setTitle(spanString);
    }
    return true;
}
Sagar
  • 23,903
  • 4
  • 62
  • 62
34

If you are using menu as <android.support.design.widget.NavigationView /> then just add below line in NavigationView :

app:itemTextColor="your color"

Also available colorTint for icon, it will override color for your icon as well. For that you have to add below line:

app:itemIconTint="your color"

Example:

<android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"

        app:itemTextColor="@color/color_white"
        app:itemIconTint="@color/color_white"

        android:background="@color/colorPrimary"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/nav_header_main"
        app:menu="@menu/activity_main_drawer"/>

Hope it will help you.

Mihir Trivedi
  • 1,458
  • 18
  • 39
21

in Kotlin I wrote these extensions:

fun MenuItem.setTitleColor(color: Int) {
    val hexColor = Integer.toHexString(color).toUpperCase().substring(2)
    val html = "<font color='#$hexColor'>$title</font>"
    this.title = html.parseAsHtml()
}           



@Suppress("DEPRECATION")                                                                        
fun String.parseAsHtml(): Spanned {                                                             
    return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {                                
        Html.fromHtml(this, Html.FROM_HTML_MODE_LEGACY)                                         
    } else {                                                                                    
        Html.fromHtml(this)                                                                     
    }                                                                                           
}  

and used like this:

menu.findItem(R.id.main_settings).setTitleColor(Color.RED)
Amir Khorsandi
  • 3,542
  • 1
  • 34
  • 38
  • Really like this solution, very neat! – Jamil Aug 22 '18 at 09:55
  • Thanks, simple and quick solution. For API > 24 it works without that second ext function – laszlo Sep 05 '19 at 11:46
  • Excellent! I've been looking for a way to grey out a menu item when disabled and this works perfectly! Menu.findItrm fails however for items in a submenu. For those look for items with submenus and search the submenu. – steven smith May 02 '22 at 02:10
  • The only solution that worked for an individual item on a fragment-based menu, thank you for sharing! – kelvin Jul 11 '22 at 19:28
17

as you can see in this question you should:

<item name="android:textColorPrimary">yourColor</item>

Above code changes the text color of the menu action items for API >= v21.

<item name="actionMenuTextColor">@android:color/holo_green_light</item>

Above is the code for API < v21

Community
  • 1
  • 1
Pouya Danesh
  • 1,557
  • 2
  • 19
  • 36
10

I used the html tag to change a single item's text colour when the menu item is inflated. Hope it would be helpful.

public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_main, menu);
    menu.findItem(R.id.main_settings).setTitle(Html.fromHtml("<font color='#ff3824'>Settings</font>"));
    return true;
}
alijandro
  • 11,627
  • 2
  • 58
  • 74
  • 1
    This does not work for me on Marshmallow. The text is applied, but not the colour. – Ollie C May 12 '16 at 14:39
  • Regarding Marshmallow, probably it doesn't work for the same reason stated in max.mustermann's answer, "solutions work only for item in overflow." – Jose_GD Nov 30 '16 at 04:24
  • This method works. The other method. `menu.getItem(position)` does not work – Oush Feb 18 '21 at 09:55
10

SIMPLEST way to make custom menu color for single toolbar, not for AppTheme

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay.MenuBlue">
        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"/>
    </android.support.design.widget.AppBarLayout>

usual toolbar on styles.xml

<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar"/>

our custom toolbar style

<style name="AppTheme.AppBarOverlay.MenuBlue">
    <item name="actionMenuTextColor">@color/blue</item>
</style>
AndrewS
  • 7,418
  • 8
  • 35
  • 50
10

I was using Material design and when the toolbar was on a small screen clicking the more options would show a blank white drop down box. To fix this I think added this to the main AppTheme:

<style name="AppTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
    <item name="android:itemTextAppearance">@style/menuItem</item>
</style>

And then created a style where you set the textColor for the menu items to your desired colour.

<style name="menuItem" parent="Widget.AppCompat.TextView.SpinnerItem">
    <item name="android:textColor">@color/black</item>
</style>

The parent name Widget.AppCompat.TextView.SpinnerItem I don't think that matters too much, it should still work.

blackers
  • 164
  • 1
  • 6
  • Because the popup menu is like the spinner for the toolbar, so it has change the text color to white while using the search view in the toolbar white working fine on other screens. Works perfect after using above style. Thanks. – DevChamp Nov 24 '21 at 13:14
8

to change menu item text color use below code

<style name="AppToolbar" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:itemTextAppearance">@style/menu_item_color</item>
</style>

where

<style name="menu_item_color">
<item name="android:textColor">@color/app_font_color</item>
</style>
6

Thanks for the code example. I had to modify it go get it to work with a context menu. This is my solution.

    static final Class<?>[] constructorSignature = new Class[] {Context.class, AttributeSet.class};

class MenuColorFix implements LayoutInflater.Factory {
    public View onCreateView(String name, Context context, AttributeSet attrs) {
        if (name.equalsIgnoreCase("com.android.internal.view.menu.ListMenuItemView")) {
            try {
                Class<? extends ViewGroup> clazz = context.getClassLoader().loadClass(name).asSubclass(ViewGroup.class);
                Constructor<? extends ViewGroup> constructor = clazz.getConstructor(constructorSignature);
                final ViewGroup view = constructor.newInstance(new Object[]{context,attrs});

                new Handler().post(new Runnable() {
                    public void run() {
                        try {
                            view.setBackgroundColor(Color.BLACK);
                            List<View> children = getAllChildren(view);
                            for(int i = 0; i< children.size(); i++) {
                                View child = children.get(i);
                                if ( child instanceof TextView ) {
                                    ((TextView)child).setTextColor(Color.WHITE);
                                }
                            }
                        }
                        catch (Exception e) {
                            Log.i(TAG, "Caught Exception!",e);
                        }

                    }
                });
                return view;
            }
            catch (Exception e) {
                Log.i(TAG, "Caught Exception!",e);
            }
        }
        return null;
    }       
}

public List<View> getAllChildren(ViewGroup vg) {
    ArrayList<View> result = new ArrayList<View>();
    for ( int i = 0; i < vg.getChildCount(); i++ ) {
        View child = vg.getChildAt(i);
        if ( child instanceof ViewGroup) {
            result.addAll(getAllChildren((ViewGroup)child));
        }
        else {
            result.add(child);
        }
    }
    return result;
}

@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
    LayoutInflater lInflater = getLayoutInflater();
    if ( lInflater.getFactory() == null ) {
        lInflater.setFactory(new MenuColorFix());
    }
    super.onCreateContextMenu(menu, v, menuInfo);
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.myMenu, menu);
}

For me this works with Android 1.6, 2.03 and 4.03.

Michael Vogl
  • 61
  • 1
  • 3
  • If you're doing the above then you should just look at using Marcus Wolschon solution. Much simpler. – chubbsondubs Jun 06 '12 at 16:40
  • The xml solution doesn't work for me on e.g. 2.3.x, but this works like a charm - also on 4.x – sunlock Nov 05 '12 at 22:13
  • This solution worked the best. I had to also capture android.support.v7.internal.view.menu.ListMenuItemView to get the styles applied on devices using the compatibility library – Chiatar Sep 14 '13 at 15:34
  • This fix will not work with Google Maps v2 - the super method must be called 1st in order for the maps to render correctly. – Chiatar Oct 09 '13 at 15:54
6

The short answer is YES. lucky you!
To do so, you need to override some styles of the Android default styles :

First, look at the definition of the themes in Android :

<style name="Theme.IconMenu">
<!-- Menu/item attributes -->
<item name="android:itemTextAppearance">@android:style/TextAppearance.Widget.IconMenu.Item</item>
<item name="android:itemBackground">@android:drawable/menu_selector</item>
<item name="android:itemIconDisabledAlpha">?android:attr/disabledAlpha</item>
<item name="android:horizontalDivider">@android:drawable/divider_horizontal_bright</item>
<item name="android:verticalDivider">@android:drawable/divider_vertical_bright</item>
<item name="android:windowAnimationStyle">@android:style/Animation.OptionsPanel</item>
<item name="android:moreIcon">@android:drawable/ic_menu_more</item>
<item name="android:background">@null</item>
</style>

So, the appearance of the text in the menu is in @android:style/TextAppearance.Widget.IconMenu.Item
Now, in the definition of the styles :

<style name="TextAppearance.Widget.IconMenu.Item" parent="TextAppearance.Small">
<item name="android:textColor">?textColorPrimaryInverse</item>
</style>

So now we have the name of the color in question, if you look in the color folder of the resources of the system :

<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="false" android:color="@android:color/bright_foreground_light_disabled" /> 
<item android:state_window_focused="false" android:color="@android:color/bright_foreground_light" /> 
<item android:state_pressed="true" android:color="@android:color/bright_foreground_light" /> 
<item android:state_selected="true" android:color="@android:color/bright_foreground_light" /> 
<item android:color="@android:color/bright_foreground_light" /> 
<!--  not selected --> 
</selector>

Finally, here is what you need to do :

Override "TextAppearance.Widget.IconMenu.Item" and create your own style. Then link it to your own selector to make it the way you want. Hope this helps you. Good luck!

Sephy
  • 50,022
  • 30
  • 123
  • 131
  • Thanks for replying. I have done what you suggested but it do not change the color of menu item – sunil Aug 26 '10 at 10:29
  • Actually, I just realized by reading more of the menu stuff that it is much more complicated than I thought If you don't want to create your own full custom menu... This will need some more reading for me, I'll keep you posted here if i find more. – Sephy Aug 26 '10 at 19:42
  • It is not possible to override "TextAppearance.Widget.IconMenu.Item". – peceps Jul 01 '11 at 11:11
  • This answer is misleading.. so the conclusion is, it doesn't work and is much harder/long winded to achieve than originally thought? – speedynomads Mar 24 '16 at 15:17
6

Options menu in android can be customized to set the background or change the text appearance. The background and text color in the menu couldn’t be changed using themes and styles. The android source code (data\res\layout\icon_menu_item_layout.xml)uses a custom item of class “com.android.internal.view.menu.IconMenuItem”View for the menu layout. We can make changes in the above class to customize the menu. To achieve the same, use LayoutInflater factory class and set the background and text color for the view.


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.my_menu, menu);
    getLayoutInflater().setFactory(new Factory() {
        @Override
        public View onCreateView(String name, Context context, AttributeSet attrs) {
            if (name .equalsIgnoreCase(“com.android.internal.view.menu.IconMenuItemView”)) {
                try{
                    LayoutInflater f = getLayoutInflater();
                    final View view = f.createView(name, null, attrs);
                    new Handler().post(new Runnable() {
                        public void run() {
                            // set the background drawable
                            view .setBackgroundResource(R.drawable.my_ac_menu_background);

                            // set the text color
                            ((TextView) view).setTextColor(Color.WHITE);
                        }
                    });
                    return view;
                } catch (InflateException e) {
                    } catch (ClassNotFoundException e) {}
            }
            return null;
        }
    });
    return super.onCreateOptionsMenu(menu);
}


Terrance
  • 11,764
  • 4
  • 54
  • 80
Abhay Kumar
  • 1,582
  • 1
  • 19
  • 45
  • 3
    `03-23 19:45:25.134: E/AndroidRuntime(26761): java.lang.IllegalStateException: A factory has already been set on this LayoutInflater` – To Kra Mar 23 '15 at 19:48
  • This works for the first time . When you open menu for second time you get exception. – LoveForDroid Aug 11 '17 at 16:34
5

i found it Eureka !!

in your app theme:

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="android:actionBarStyle">@style/ActionBarTheme</item>
    <!-- backward compatibility -->          
    <item name="actionBarStyle">@style/ActionBarTheme</item>        
</style>

here is your action bar theme:

<style name="ActionBarTheme" parent="@style/Widget.AppCompat.Light.ActionBar.Solid.Inverse">
   <item name="android:background">@color/actionbar_bg_color</item>
   <item name="popupTheme">@style/ActionBarPopupTheme</item
   <!-- backward compatibility -->
   <item name="background">@color/actionbar_bg_color</item>
</style>

and here is your popup theme:

 <style name="ActionBarPopupTheme">
    <item name="android:textColor">@color/menu_text_color</item>
    <item name="android:background">@color/menu_bg_color</item>
 </style>

Cheers ;)

Fareed Alnamrouti
  • 30,771
  • 4
  • 85
  • 76
5

Simply add this to your theme

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="android:itemTextAppearance">@style/AppTheme.ItemTextStyle</item>
</style>

<style name="AppTheme.ItemTextStyle" parent="@android:style/TextAppearance.Widget.IconMenu.Item">
        <item name="android:textColor">@color/orange_500</item>
</style>

Tested on API 21

Pham Quan
  • 131
  • 2
  • 4
  • 2
    It's better to use ` – Mr-IDE Oct 31 '17 at 12:54
4

Thanks to max.musterman, this is the solution I got to work in level 22:

public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu_main, menu);
    SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
    MenuItem searchMenuItem = menu.findItem(R.id.search);
    SearchView searchView = (SearchView) searchMenuItem.getActionView();
    searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
    searchView.setSubmitButtonEnabled(true);
    searchView.setOnQueryTextListener(this);
    setMenuTextColor(menu, R.id.displaySummary, R.string.show_summary);
    setMenuTextColor(menu, R.id.about, R.string.text_about);
    setMenuTextColor(menu, R.id.importExport, R.string.import_export);
    setMenuTextColor(menu, R.id.preferences, R.string.settings);
    return true;
}

private void setMenuTextColor(Menu menu, int menuResource, int menuTextResource) {
    MenuItem item = menu.findItem(menuResource);
    SpannableString s = new SpannableString(getString(menuTextResource));
    s.setSpan(new ForegroundColorSpan(Color.BLACK), 0, s.length(), 0);
    item.setTitle(s);
}

The hardcoded Color.BLACK could become an additional parameter to the setMenuTextColor method. Also, I only used this for menu items which were android:showAsAction="never".

lightkeeper
  • 327
  • 1
  • 3
  • 11
4

Adding this into my styles.xml worked for me

<item name="android:textColorPrimary">?android:attr/textColorPrimaryInverse</item>
Asim
  • 161
  • 1
  • 12
4

If you want to set color for an individual menu item, customizing a toolbar theme is not the right solution. To achieve this, you can make use of android:actionLayout and an action view for the menu item.

First create an XML layout file for the action view. In this example we use a button as an action view:

menu_button.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/menuButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Done"
        android:textColor="?android:attr/colorAccent"
        style="?android:attr/buttonBarButtonStyle"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

In the code snippet above, we use android:textColor="?android:attr/colorAccent" to customize button text color.

Then in your XML layout file for the menu, include app:actionLayout="@layout/menu_button" as shown below:

main_menu.xml

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

    <item
        android:id="@+id/menuItem"
        android:title=""
        app:actionLayout="@layout/menu_button"
        app:showAsAction="always"/>
</menu>

Last override the onCreateOptionsMenu() method in your activity:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.main_menu, menu);
    MenuItem item = menu.findItem(R.id.menuItem);
    Button saveButton = item.getActionView().findViewById(R.id.menuButton);
    saveButton.setOnClickListener(view -> {
        // Do something
    });
    return true;
}

...or fragment:

@Override
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater){
    inflater.inflate(R.menu.main_menu, menu);
    MenuItem item = menu.findItem(R.id.menuItem);
    Button saveButton = item.getActionView().findViewById(R.id.menuButton);
    button.setOnClickListener(view -> {
        // Do something
    });
}

For more details on action views, see the Android developer guide.

Nitin Kabra
  • 3,146
  • 10
  • 43
  • 62
3

You can set color programmatically.

private static void setMenuTextColor(final Context context, final Toolbar toolbar, final int menuResId, final int colorRes) {
    toolbar.post(new Runnable() {
        @Override
        public void run() {
            View settingsMenuItem =  toolbar.findViewById(menuResId);
            if (settingsMenuItem instanceof TextView) {
                if (DEBUG) {
                    Log.i(TAG, "setMenuTextColor textview");
                }
                TextView tv = (TextView) settingsMenuItem;
                tv.setTextColor(ContextCompat.getColor(context, colorRes));
            } else { // you can ignore this branch, because usually there is not the situation
                Menu menu = toolbar.getMenu();
                MenuItem item = menu.findItem(menuResId);
                SpannableString s = new SpannableString(item.getTitle());
                s.setSpan(new ForegroundColorSpan(ContextCompat.getColor(context, colorRes)), 0, s.length(), 0);
                item.setTitle(s);
            }

        }
    });
}
Victor Choy
  • 4,006
  • 28
  • 35
2
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.search, menu);


    MenuItem myActionMenuItem = menu.findItem( R.id.action_search);
    SearchView searchView = (SearchView) myActionMenuItem.getActionView();

    EditText searchEditText = (EditText) searchView.findViewById(android.support.v7.appcompat.R.id.search_src_text);
    searchEditText.setTextColor(Color.WHITE); //You color here
Peter R
  • 384
  • 1
  • 11
2

My situation was settings text color in the options menu (main app menu showed on menu button press).

Tested in API 16 with appcompat-v7-27.0.2 library, AppCompatActivity for MainActivity and AppCompat theme for the application in AndroidManifest.xml.

styles.xml:

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
  <item name="actionBarPopupTheme">@style/PopupTheme</item>
</style>

<style name="PopupTheme" parent="@style/ThemeOverlay.AppCompat.Light">
  <item name="android:textColorSecondary">#f00</item>
</style>

Don't know if that textColorSecondary affects other elements but it controls the menu text color.


I searched some examples on the topic but all ready-to-use snippets didn't work.

So I wanted to investigate it with the source code for the appcompat-v7 library (specifically with the res folder of the .aar package).

Though in my case I used Eclipse with exploded .aar dependencies. So I could change the default styles and check the results. Don't know how to explode the libraries to use with Gradle or Android Studio directly. It deserves another thread of investigation.

So my purpose was so find which color in the res/values/values.xml file is used for the menu text (I was almost sure the color was there).

  1. I opened that file, then duplicated all colors, put them below the default ones to override them and assigned #f00 value to all of them.
  2. Start the app.
  3. Many elements had red background or text color. And the menu items too. That was what I needed.
  4. Removing my added colors by blocks of 5-10 lines I ended with the secondary_text_default_material_light color item.
  5. Searching that name in the files within the res folder (or better within res/colors) I found only one occurrence in the color/abc_secondary_text_material_light.xml file (I used Sublime Text for these operations so it's easier to find thing I need).
  6. Back to the values.xml 8 usages were found for the @color/abc_secondary_text_material_light.
  7. It was a Light theme so 4 left in 2 themes: Base.ThemeOverlay.AppCompat.Light and Platform.AppCompat.Light.
  8. The first theme was a child of the second one so there were only 2 attributes with that color resource: android:textColorSecondary and android:textColorTertiaryin the Base.ThemeOverlay.AppCompat.Light.
  9. Changing their values directly in the values.xml and running the app I found that the final correct attribute was android:textColorSecondary.
  10. Next I needed a theme or another attribute so I could change it in my app's style.xml (because my theme had as the parent the Theme.AppCompat.Light and not the ThemeOverlay.AppCompat.Light).
  11. I searched in the same file for the Base.ThemeOverlay.AppCompat.Light. It had a child ThemeOverlay.AppCompat.Light.
  12. Searching for the ThemeOverlay.AppCompat.Light I found its usage in the Base.Theme.AppCompat.Light.DarkActionBar theme as the actionBarPopupTheme attribute value.
  13. My app's theme Theme.AppCompat.Light.DarkActionBar was a child of the found Base.Theme.AppCompat.Light.DarkActionBar so I could use that attribute in my styles.xml without problems.
  14. As it's seen in the example code above I created a child theme from the mentioned ThemeOverlay.AppCompat.Light and changed the android:textColorSecondary attribute.

https://i.stack.imgur.com/plzdq.png

mortalis
  • 2,060
  • 24
  • 34
2

Add textColor as below

<style name="MyTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light">
    <item name="android:textColor">@color/radio_color_gray</item>
</style>

and use it in Toolbar in xml file

<androidx.appcompat.widget.Toolbar
     android:id="@+id/toolbar"
     android:layout_width="match_parent"
     android:layout_height="?attr/actionBarSize"
     app:popupTheme="@style/MyTheme.PopupOverlay" /> 
Ahmet B.
  • 1,290
  • 10
  • 20
1

try this code....

 @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
         inflater.inflate(R.menu.my_menu, menu);

        getLayoutInflater().setFactory(new Factory() {
            @Override
            public View onCreateView(String name, Context context,
                    AttributeSet attrs) {

                if (name.equalsIgnoreCase("com.android.internal.view.menu.IconMenuItemView")) {
                    try {
                        LayoutInflater f = getLayoutInflater();
                        final View view = f.createView(name, null, attrs);

                        new Handler().post(new Runnable() {
                            public void run() {

                                // set the background drawable
                                 view.setBackgroundResource(R.drawable.my_ac_menu_background);

                                // set the text color
                                ((TextView) view).setTextColor(Color.WHITE);
                            }
                        });
                        return view;
                    } catch (InflateException e) {
                    } catch (ClassNotFoundException e) {
                    }
                }
                return null;
            }
        });
        return super.onCreateOptionsMenu(menu);
    }
Jitendra
  • 1,015
  • 9
  • 24
Anoop
  • 993
  • 6
  • 16
  • 1
    on Android > 4.0 i'm getting `java.lang.IllegalStateException: A factory has already been set on this LayoutInflater` – To Kra Mar 23 '15 at 20:18
1

Sephy's solution doesn't work. It's possible to override the options menu item text appearance using the method described above, but not the item or menu. To do that there are essentially 3 ways:

  1. How to change the background color of the options menu?
  2. Write your own view to display and override onCreateOptionsMenu and onPrepareOptionsMenu to get the results you want. I state this generally because you can generally do whatever you want in these methods, but you probably won't want to call into super().
  3. Copy code from the open-source SDK and customize for your behavior. The default menu implementation used by Activity will no longer apply.

See Issue 4441: Custom Options Menu Theme for more clues.

Community
  • 1
  • 1
Tenacious
  • 594
  • 4
  • 6
  • To reiterate...Sephy's solution works for the menu item TextAppearance, though what I've done is override the default through a themes.xml. Also, #2 or #3 above should be aware that calling through to super#onCreateOptionsMenu/super#onPrepareOptionsMenu is designed to place system menu items...as indicated in the javadoc for Activity#onCreateOptionsMenu() . That may/may not matter for your app. – Tenacious Oct 17 '10 at 10:42
  • What Sephy is describing is to have this in your themes.xml: @style/Text_MenuItemText Then define something like this in your styles.xml: That's as easy as it gets. Was that what you meant? Deeper options-menu customization isn't easy at all, but I intend to post a blog article about it soon. – Tenacious Nov 26 '10 at 08:03
0

This is how you can color a specific menu item with color, works for all API levels:

public static void setToolbarMenuItemTextColor(final Toolbar toolbar,
                                               final @ColorRes int color,
                                               @IdRes final int resId) {
    if (toolbar != null) {
        for (int i = 0; i < toolbar.getChildCount(); i++) {
            final View view = toolbar.getChildAt(i);
            if (view instanceof ActionMenuView) {
                final ActionMenuView actionMenuView = (ActionMenuView) view;
                // view children are accessible only after layout-ing
                actionMenuView.post(new Runnable() {
                    @Override
                    public void run() {
                        for (int j = 0; j < actionMenuView.getChildCount(); j++) {
                            final View innerView = actionMenuView.getChildAt(j);
                            if (innerView instanceof ActionMenuItemView) {
                                final ActionMenuItemView itemView = (ActionMenuItemView) innerView;
                                if (resId == itemView.getId()) {
                                    itemView.setTextColor(ContextCompat.getColor(toolbar.getContext(), color));
                                }
                            }
                        }
                    }
                });
            }
        }
    }
}

By doing that you loose the background selector effect, so here is the code to apply a custom background selector to all of the menu item children.

public static void setToolbarMenuItemsBackgroundSelector(final Context context,
                                                         final Toolbar toolbar) {
    if (toolbar != null) {
        for (int i = 0; i < toolbar.getChildCount(); i++) {
            final View view = toolbar.getChildAt(i);
            if (view instanceof ImageButton) {
                // left toolbar icon (navigation, hamburger, ...)
                UiHelper.setViewBackgroundSelector(context, view);
            } else if (view instanceof ActionMenuView) {
                final ActionMenuView actionMenuView = (ActionMenuView) view;

                // view children are accessible only after layout-ing
                actionMenuView.post(new Runnable() {
                    @Override
                    public void run() {
                        for (int j = 0; j < actionMenuView.getChildCount(); j++) {
                            final View innerView = actionMenuView.getChildAt(j);
                            if (innerView instanceof ActionMenuItemView) {
                                // text item views
                                final ActionMenuItemView itemView = (ActionMenuItemView) innerView;
                                UiHelper.setViewBackgroundSelector(context, itemView);

                                // icon item views
                                for (int k = 0; k < itemView.getCompoundDrawables().length; k++) {
                                    if (itemView.getCompoundDrawables()[k] != null) {
                                        UiHelper.setViewBackgroundSelector(context, itemView);
                                    }
                                }
                            }
                        }
                    }
                });
            }
        }
    }
}

Here is the helper function also:

public static void setViewBackgroundSelector(@NonNull Context context, @NonNull View itemView) {
    int[] attrs = new int[]{R.attr.selectableItemBackgroundBorderless};
    TypedArray ta = context.obtainStyledAttributes(attrs);
    Drawable drawable = ta.getDrawable(0);
    ta.recycle();

    ViewCompat.setBackground(itemView, drawable);
}
box
  • 4,450
  • 2
  • 38
  • 38
0

For changing the text color, you can just set a custom view for the MenuItem, and then you can define the color for the text.

Sample Code : MenuItem.setActionView()

leisure
  • 1
  • 2
  • While this code snippet may solve the question, [including an explanation](http://meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion. – Mischa Aug 24 '17 at 10:11
-4

Simply just go to Values - styles and inside styles and type your color