如何在Android中更改菜单项的文本颜色?


175

我可以在Android中更改菜单项的背景颜色吗?

请让我知道是否有人对此有任何解决方案。最后一个选项显然是自定义它,但是有任何方法可以更改文本颜色而不自定义它。


有谁能让我知道解决方案吗?
sunil 2010年

3
您要更改文本颜色,文本视图的背景颜色吗?或两者?两者是不同的东西。请重新提出问题。
Abhinav Saxena 2014年

Answers:


335

您主题中的简单一行:)

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

19
注意:此选项必须输入应用程序的主主题定义,而不是actionBarStyle例如。actionBarStyle即使看起来很合理,它也无法在其中工作!
Colin M.

47
要支持较低的API版本,<item name="actionMenuTextColor">@color/your_color</item>请不要使用Android名称空间
alex.p

5
@ColinM。它必须成为一个主题。如果theme在工具栏上设置属性,则可以使用。
DariusL

2
有或没有android:命名空间都不适合我。它已添加到主应用程序主题。
racs

2
我仍然完全无法更改文本颜色。我的整体主题textcolor只是优先考虑。有什么帮助吗?这些答案均无效。
David P

114

似乎

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

在我的主题中

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

在styles.xml中,更改列表项的样式,但不更改菜单项。


5
这对于上下文菜单项(不是菜单按钮中的菜单项)非常有用,这正是我一直在寻找的东西。比整个LayoutFactory混乱简单得多。
chubbsondubs 2012年

android:itemTextAppearance属性不能放在一个风格,其父母为内parent="@android:style/Widget.Holo.ListPopupWindow",因为这将无法正常显示。它必须是顶层样式,例如其父对象为android:Theme.Holo.Light.DarkActionBar
toobsco42

我应该在哪里添加<item name =“ android:itemTextAppearance”> @ style / myCustomMenuTextApearance </ item>?
Bagusflyer 2014年

@bagusflyer,您应该在主题的根样式中添加该样式,即是Theme.HoloTheme.Holo.Light.DarkActionBar或类似的子样式。
Tash Pemhiwa 2014年

86

您可以MenuItem使用SpannableString代替轻松更改文本的颜色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);
}

10
这对我来说在4.4和5+版本中都有效,menu.findItem(R.id.menu_item_id);而不是使用menu.getItem()
haagmm

1
也为我工作[使用findItem(...)]。
呆呆的

6
解决方案仅适用于溢出的项目。...我将无法更改通过设置showAsAction:“ always”可见的项目颜色
Junaid

56

如果使用主题为的新工具栏,则Theme.AppCompat.Light.NoActionBar可以通过以下方式设置其样式。

 <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>`

根据我得到的结果,
android:textColorPrimary是显示您的活动名称的文本颜色,它是工具栏的主要文本。

android:textColorSecondary是字幕和更多选项(3点)按钮的文本颜色。(是的,它根据此属性更改了颜色!)

android:textColor是包括菜单在内的所有其他文本的颜色。

最后将主题设置为工具栏

<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"/>

哪个项目控制在工具栏上显示为操作(文本)的按钮上的文本?android:textColorPrimary,android:textColorSecondary和android:textColor似乎都不会影响它们。
LarsH '17

在前面的评论中回答我的问题:(android:actionMenuTextColor请参阅stackoverflow.com/a/5538709/423105)。
LarsH '17

32

如果您使用菜单,<android.support.design.widget.NavigationView />则只需在下面添加以下行NavigationView

app:itemTextColor="your color"

图标也可以使用colorTint,它也会覆盖图标的颜色。为此,您必须在下面添加行:

app:itemIconTint="your color"

例:

<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"/>

希望对您有帮助。


这更改了嵌套在另一个项目中的项目,但没有更改包含其他项目的项目。您知道我也可以更改它们吗?
Dinu Nicolae

@DinuNicolae能否请您发布示例屏幕截图?或提供更多细节。
Mihir Trivedi

我有<item> <menu> <inside items> </ menu> </ item>,只有内部项目的颜色发生了变化
Dinu Nicolae

31

我像这样以编程方式进行处理:

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;
}

2
您的回答帮助我将MenuItem文本设置为粗体。(s.setSpan(new StyleSpan(android.graphics.Typeface.BOLD),0,s.length(),0);谢谢!
ArkadiuszCieśliński15年

此解决方案帮助解决了我的问题。我喜欢它,因为它不依赖于主题相关的条件。
Tomcat

15

正如您在此问题中看到的,您应该:

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

上面的代码更改了API> = v21的菜单操作项的文本颜色。

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

上面是API <v21的代码


谢谢。这应该被接受。简单又容易
Pooja

10

当菜单项膨胀时,我使用了html标签来更改单个项的文本颜色。希望对您有所帮助。

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;
}

1
这在棉花糖上对我不起作用。将应用文本,但不应用颜色。
奥利·C

对于棉花糖,可能由于max.mustermann的回答“解决方案仅适用于溢出的项目”而无法正常工作。
Jose_GD

10

为单个工具栏而不是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>

styles.xml上的常用工具栏

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

我们的自定义工具栏样式

<style name="AppTheme.AppBarOverlay.MenuBlue">
    <item name="actionMenuTextColor">@color/blue</item>
</style>

很棒!最佳答案。
贝贝

9

在Kotlin中,我编写了以下扩展名:

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)                                                                     
    }                                                                                           
}  

并像这样使用:

menu.findItem(R.id.main_settings).setTitleColor(Color.RED)

真的很喜欢这种解决方案,很整洁!
贾米尔·纳瓦兹

谢谢,简单快速的解决方案。对于API> 24,它无需第二个ext函数就可以工作
laszlo

7

简短的回答是“是”。幸运的你!
为此,您需要重写一些Android默认样式的样式:

首先,查看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>

因此,菜单中文本的外观在样式@android:style/TextAppearance.Widget.IconMenu.Item
定义中 Now中:

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

因此,如果您在系统资源的color文件夹中查找,那么我们现在有了相关颜色的名称:

<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>

最后,这是您需要做的:

覆盖“ TextAppearance.Widget.IconMenu.Item”并创建自己的样式。然后将其链接到您自己的选择器,使其成为您想要的方式。希望这对您有帮助。祝好运!


感谢回复。我已经按照您的建议做了,但它不会改变菜单项的颜色
sunil 2010年

实际上,我只是通过阅读更多的菜单知识才意识到,它比我想的要复杂得多。如果您不想创建自己的完整自定义菜单...这将需要我多读一些,如果我发现更多信息,您会在这里发布。
Sephy

无法覆盖“ TextAppearance.Widget.IconMenu.Item”。
pepseps

这个答案具有误导性。.因此,结论是,它不起作用,并且比原先想的要难/容易得多吗?
speedynomads

6

可以在android中自定义选项菜单,以设置背景或更改文本外观。菜单中的背景和文字颜色无法使用主题和样式进行更改。android源代码(data \ res \ layout \ icon_menu_item_layout.xml)使用“ com.android.internal.view.menu.IconMenuItem” View类的自定义项进行菜单布局。我们可以在上述类中进行更改以自定义菜单。为此,请使用LayoutInflater工厂类并为视图设置背景和文本颜色。


@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);
}



3
03-23 19:45:25.134: E/AndroidRuntime(26761): java.lang.IllegalStateException: A factory has already been set on this LayoutInflater
要克拉

这是第一次。当您第二次打开菜单时,您将获得例外。
LoveForDroid

6

感谢您的代码示例。我必须修改它才能使其与上下文菜单一起使用。这是我的解决方案。

    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);
}

对我来说,这适用于Android 1.6、2.03和4.03。


如果执行上述操作,则应该只考虑使用Marcus Wolschon解决方案。简单得多。
chubbsondubs 2012年

该XML解决方案不工作我就如2.3.x版本,但是这个作品就像一个魅力-也4.x的
sunlock

此解决方案效果最佳。我还必须捕获android.support.v7.internal.view.menu.ListMenuItemView才能使用兼容性库获得应用到设备上的样式
Chiatar

此修复程序不适用于Google Maps v2-必须调用超级方法1st才能正确渲染地图。
Chiatar 2013年

5

我发现它尤里卡!

在您的应用主题中:

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

这是您的操作栏主题:

<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>

这是您的弹出主题:

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

干杯;)


5

更改菜单项的文本颜色,请使用以下代码

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

哪里

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

4

感谢max.musterman,这是我在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);
}

硬编码Color.BLACK可能会成为该setMenuTextColor方法的附加参数。另外,我仅将其用于菜单项android:showAsAction="never"


无法在API 24上为我工作。有什么想法吗?被困了好几天...太荒谬了!
David P

不知道该怎么说。在API 25中,这对我来说很好用
。– lightkeeper

3

您可以通过编程设置颜色。

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);
            }

        }
    });
}

3

将其添加到我的styles.xml中对我有用

<item name="android:textColorPrimary">?android:attr/textColorPrimaryInverse</item>

2

只需将其添加到您的主题

<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>

经过API 21测试


2
最好使用<style name="AppTheme.ItemTextStyle" parent="@android:style/TextAppearance.Widget">,否则文本在溢出菜单中显得太小。另请注意,此技术仅适用于Android 5及更高版本。
Mr-IDE

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

1
解释你的答案
Coder

1
如果不是SearchView怎么办?
nasch

2

我的情况是在选项菜单中设置文本颜色(按菜单按钮时显示主应用程序菜单)。

经测试,在API 16程序兼容性-v7-27.0.2库,AppCompatActivity用于MainActivityAppCompat主题中应用的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>

不知道这是否textColorSecondary会影响其他元素,但会控制菜单文本的颜色。


我搜索了有关该主题的一些示例,但是所有即时可用的摘录均无效。

因此,我想使用appcompat-v7库的源代码(特别是.aar软件包的res文件夹)进行调查。

尽管在我的情况下,我使用了带有爆炸性.aar依赖项的Eclipse 。因此,我可以更改默认样式并检查结果。不知道如何爆炸这些库以直接用于GradleAndroid Studio。它值得进行另一项调查。

因此,我的目的是找到res / values / values.xml文件中的哪种颜色用于菜单文本(我几乎确定该颜色在那里)。

  1. 我打开了该文件,然后复制了所有颜色,将它们置于默认颜色之下以覆盖它们并进行分配 #f00值。
  2. 启动应用程序。
  3. 许多元素具有红色背景或文本颜色。还有菜单项。那就是我所需要的。
  4. 以5至10行的块来删除我添加的颜色,我以secondary_text_default_material_light颜色项结束。
  5. res文件夹中的文件中搜索该名称(或者在res / colors中更好),我在color / abc_secondary_text_material_light.xml文件中只发现了一个(我对这些操作使用了Sublime Text,因此更容易找到我需要的东西)。
  6. 回到values.xml,发现了8种用法@color/abc_secondary_text_material_light
  7. 这是一个Light主题,所以在2个主题中还剩下4个:Base.ThemeOverlay.AppCompat.LightPlatform.AppCompat.Light
  8. 第一个主题是第二个主题的子主题,因此该颜色资源只有2个属性:android:textColorSecondaryandroid:textColorTertiary中的Base.ThemeOverlay.AppCompat.Light
  9. 直接在values.xml中更改它们的值并运行应用程序,我发现最终的正确属性是android:textColorSecondary
  10. 接下来,我需要一个主题或其他属性,以便可以在应用程序的style.xml中进行更改(因为我的主题以Theme.AppCompat.Light而不是作为父元素ThemeOverlay.AppCompat.Light)。
  11. 我在同一文件中搜索Base.ThemeOverlay.AppCompat.Light。它有一个孩子ThemeOverlay.AppCompat.Light
  12. 搜索ThemeOverlay.AppCompat.LightI,发现它在Base.Theme.AppCompat.Light.DarkActionBar主题中用作actionBarPopupTheme属性值。
  13. 我应用的主题Theme.AppCompat.Light.DarkActionBar是found的子主题,Base.Theme.AppCompat.Light.DarkActionBar因此我可以在styles.xml中使用该属性而不会出现问题。
  14. 从上面的示例代码中可以看出,我根据上述内容创建了一个子主题,ThemeOverlay.AppCompat.Light并更改了android:textColorSecondary属性。

https://i.imgur.com/LNfKdzC.png


1

Sephy的解决方案不起作用。可以使用上述方法覆盖选项菜单项的文本外观,但不能覆盖该项或菜单。为此,基本上有3种方法:

  1. 如何更改选项菜单的背景颜色?
  2. 编写您自己的视图以显示和覆盖onCreateOptionsMenu和onPrepareOptionsMenu以获得所需的结果。我之所以这样说,是因为您通常可以在这些方法中做任何您想做的事,但是您可能不想调用super()。
  3. 从开源SDK复制代码并针对您的行为进行自定义。Activity使用的默认菜单实现将不再适用。

有关更多线索,请参见问题4441:“自定义选项菜单主题 ”。


重申一下……Sephy的解决方案适用于菜单项TextAppearance,尽管我所做的是通过themes.xml覆盖了默认值。同样,上面的#2或#3应该注意,通过调用super#onCreateOptionsMenu / super#onPrepareOptionsMenu来放置系统菜单项...如Activity #onCreateOptionsMenu()的javadoc中所示。这可能/可能对您的应用无关紧要。
顽强的

Sephy所描述的是在您的themes.xml中包含此内容:<item name =“ android:itemTextAppAppance”> @ style / Text_MenuItemText </ item>然后在您的styles.xml中定义如下内容:<style name =“ Text_MenuItemText” > <item name =“ android:textSize”> 12dp </ item> <item name =“ android:textColor”>#FFFFFF </ item> </ style>就是这么简单。那是你的意思吗?更深入的选项菜单自定义根本不是一件容易的事,但是我打算很快发布一篇有关它的博客文章。
顽强的

1

试试这个代码...。

 @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);
    }

1
在Android> 4.0上获取java.lang.IllegalStateException: A factory has already been set on this LayoutInflater
到2015年

1

如果要为单个菜单项设置颜色,则自定义工具栏主题不是正确的解决方案。为此,您可以使用android:actionLayout和菜单项的操作视图。

首先为操作视图创建XML布局文件。在此示例中,我们使用按钮作为操作视图:

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>

在上面的代码段中,我们用于android:textColor="?android:attr/colorAccent"自定义按钮文本的颜色。

然后在菜单的XML布局文件中,包括app:actionLayout="@layout/menu_button"如下所示:

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>

最后覆盖onCreateOptionsMenu()您活动中的方法:

@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;
}

...或片段:

@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
    });
}

有关操作视图的更多详细信息,请参见Android开发人员指南


0

这是您可以使用特定的颜色为特定的菜单项着色的方法,适用于所有API级别:

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));
                                }
                            }
                        }
                    }
                });
            }
        }
    }
}

这样,您就可以松开背景选择器效果,因此这里是将自定义背景选择器应用于所有菜单项子级的代码。

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);
                                    }
                                }
                            }
                        }
                    }
                });
            }
        }
    }
}

这也是辅助函数:

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);
}

0

要更改文本颜色,您可以只为MenuItem设置自定义视图,然后可以定义文本的颜色。

示例代码:MenuItem.setActionView()


尽管此代码段可以解决问题,但提供说明确实有助于提高您的帖子质量。请记住,您将来会为读者回答这个问题,而这些人可能不知道您提出代码建议的原因。
米沙(Mischa),
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.