如何在Android 4.2中更改Action Bar的选项菜单背景颜色?

73

我想要改变Android 4.2中选项(溢出)菜单的背景颜色。我已经尝试了所有方法,但它仍然显示主题设置的默认颜色。我使用了以下代码和XML配置。

MainActivity.java

public class MainActivity extends Activity {

@SuppressLint("NewApi")
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    getActionBar().setIcon(R.drawable.ic_launcher);     
    getActionBar().setTitle("Sample Menu");
    getActionBar().setBackgroundDrawable(new 
               ColorDrawable(Color.parseColor("#33B5E5"))); 

    int titleId = Resources.getSystem().getIdentifier("action_bar_title", "id", "android");
    TextView titleText = (TextView)findViewById(titleId);
    titleText.setTextColor(Color.parseColor("#ffffff"));

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    setMenuBackground();
    return true;
}

protected void setMenuBackground(){                     
    // Log.d(TAG, "Enterting setMenuBackGround");  
    getLayoutInflater().setFactory( new Factory() { 

        @Override
        public View onCreateView(String name, Context context,
                AttributeSet attrs) {
            if ( name.equalsIgnoreCase( "com.android.internal.view.menu.IconMenuItemView" ) ) {
                try { // Ask our inflater to create the view  
                    LayoutInflater f = getLayoutInflater();  
                    final View view = f.createView( name, null, attrs );  
                    /* The background gets refreshed each time a new item is added the options menu.  
                    * So each time Android applies the default background we need to set our own  
                    * background. This is done using a thread giving the background change as runnable 
                    * object */
                    new Handler().post( new Runnable() {  
                        public void run () {  
                            // sets the background color   
                            view.setBackgroundResource( R.color.menubg);
                            // sets the text color              
                            ((TextView) view).setTextColor(Color.WHITE);
                            // sets the text size              
                            ((TextView) view).setTextSize(18);
            }
                    } );  
                return view;
            }
        catch ( InflateException e ) {}
        catch ( ClassNotFoundException e ) {}  
    } 
            return null;
        }});
}

}

菜单.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android" >

<item
    android:id="@+id/action_settings"
    android:icon="@drawable/menu"
    android:showAsAction="always"
    android:title="@string/action_settings">
    <menu>
        <item
            android:id="@+id/item1"             
            android:showAsAction="always"
            android:title="@string/item1" />
        <item
            android:id="@+id/item2"             
            android:showAsAction="always"
            android:title="@string/item2" />
        <item
            android:id="@+id/item3"
            android:showAsAction="always"
            android:title="@string/item3" />
        <item
            android:id="@+id/item4"
            android:showAsAction="always"
            android:title="@string/item4" />
    </menu>
</item>

</menu>

color.xml

<color name="menubg">#33B5E5</color>

上述的setMenuBackground没有起作用:

菜单示例

在上图中,我想将操作栏中菜单的背景从黑色更改为蓝色。我该怎么做才能实现这一点,我哪里错了?


请参考下面的链接 https://dev59.com/Gobca4cB1Zd3GeqPYKCs - Pavan Pyati
16个回答

95
如果有人仍在寻找一个可行的解决方案,以下是适用于Appcompat支持库的解决方法。这是对操作栏样式的延续, 在这里解释
下面是styles.xml文件。
<resources>
    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light">
        <!-- This is the styling for action bar -->
        <item name="actionBarStyle">@style/MyActionBar</item>
        <!--To change the text styling of options menu items</item>-->
        <item name="android:itemTextAppearance">@style/MyActionBar.MenuTextStyle</item>
        <!--To change the background of options menu-->
        <item name="android:itemBackground">@color/skyBlue</item>
    </style>

    <style name="MyActionBar" parent="@style/Widget.AppCompat.Light.ActionBar.Solid.Inverse">
        <item name="background">@color/red</item>
        <item name="titleTextStyle">@style/MyActionBarTitle</item>
    </style>

    <style name="MyActionBarTitle" parent="@style/TextAppearance.AppCompat.Widget.ActionBar.Title">
        <item name="android:textColor">@color/white</item>
    </style>

    <style name="MyActionBar.MenuTextStyle"
        parent="style/TextAppearance.AppCompat.Widget.ActionBar.Title">
        <item name="android:textColor">@color/red</item>
        <item name="android:textStyle">bold</item>
        <item name="android:textSize">25sp</item>
    </style>
</resources>

以下是它的显示效果——MenuItem 的背景颜色为天蓝色,文本颜色为粉色,使用25sp的文本大小:

enter image description here


1
谢谢@Nicks,android:itemBackground 对我有用,而 android:popupBackground 不行。 - Ninja
2
是的,应用程序兼容性问题非常琐碎,如果不是因为这个网站,我永远也想不到原来如此复杂。 - user798719
3
感谢你阻止我疯掉(AppCompat 太糟糕了)。 - SoliQuiD
3
这会消除涟漪效应 :( - David Velasquez
1
虽然这很有效,但它会移除默认字体和波纹效果,甚至是圆角。 - ElliotM
显示剩余3条评论

90

操作栏样式生成器由Sunny推荐,非常有用,但它会生成很多文件,如果您只想更改背景颜色,则大多数文件都是无关紧要的。

因此,我深入研究了它生成的压缩包,并尝试缩小了重点范围,这样我就可以对我的应用程序进行最少量的更改。以下是我发现的内容。


在样式生成器中,相关设置是弹出色,它会影响"溢出菜单、子菜单和下拉面板的背景。"

enter image description here

继续生成zip文件,但是在所有生成的文件中,您只需要一个名为menu_dropdown_panel_example.9.png的图片,它看起来像这样:

enter image description here

所以,将不同分辨率版本添加到res/drawable-*中。(并且可能要将它们重命名为menu_dropdown_panel.9.png。)
然后,例如,在res/values/themes.xml中,您将拥有以下内容,其中android:popupMenuStyleandroid:popupBackground是关键设置。
<resources>

    <style name="MyAppActionBarTheme" parent="android:Theme.Holo.Light">
        <item name="android:popupMenuStyle">@style/MyApp.PopupMenu</item>
        <item name="android:actionBarStyle">@style/MyApp.ActionBar</item>
    </style>

    <!-- The beef: background color for Action Bar overflow menu -->
    <style name="MyApp.PopupMenu" parent="android:Widget.Holo.Light.ListPopupWindow">
        <item name="android:popupBackground">@drawable/menu_dropdown_panel</item>
    </style>

    <!-- Bonus: if you want to style whole Action Bar, not just the menu -->
    <style name="MyApp.ActionBar" parent="android:Widget.Holo.Light.ActionBar.Solid">
        <!-- Blue background color & black bottom border -->
        <item name="android:background">@drawable/blue_action_bar_background</item>
    </style>   

</resources>

当然,在 AndroidManifest.xml 中:

<application
    android:theme="@style/MyAppActionBarTheme" 
    ... >

使用此设置可获得以下内容:

enter image description here

请注意,我使用Theme.Holo.Light作为基本主题。如果您使用Theme.Holo(Holo Dark),则需要执行额外的步骤,如此答案所述
此外,如果您(像我一样)想要为整个操作栏设置样式,而不仅仅是菜单,请在res/drawable/blue_action_bar_background.xml中放置类似于以下内容的东西:
<!-- Bonus: if you want to style whole Action Bar, not just the menu -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >

    <item>
        <shape android:shape="rectangle">
            <stroke android:width="2dp" android:color="#FF000000" />
            <solid android:color="#FF2070B0" />                   
        </shape>
    </item>

    <item android:bottom="2dp">
        <shape android:shape="rectangle">
            <stroke android:width="2dp" android:color="#FF2070B0" />
            <solid android:color="#00000000" />
            <padding android:bottom="2dp" />
        </shape>
    </item>

</layer-list>

在Android 4.0+ (API level 14+)上运行良好。


谢谢Jonik。这对我来说很有效,使用android:popupMenuStyle和android:popupBackground更改了弹出窗口的背景颜色。您能否指导我如何更改弹出菜单中的文本颜色? - VikramV
2
@VikramV:我成功地使用android:itemTextAppearanceandroid:textColor更改了菜单文本颜色如此答案中所述 - Jonik
10
由于某种奇怪的原因,在我的安卓4.4设备上这个东西不起作用。设置完全一样... - DarkLeafyGreen
2
谢谢你的回答,对我帮助很大。不过我正在使用 android:Theme.Holo.Light.DarkActionBar,但弹出窗口没有改变。看起来这是一个 bug :-/。 - JJ86
如果您需要自定义Spinner下拉菜单的背景,我刚刚发现同样的menu_dropdown_panel图像也可以很好地解决这个问题(链接:https://dev59.com/hGgu5IYBdhLWcg3wpYYj#25523712)。 - Jonik
显示剩余3条评论

18

有一种简单的方法可以更改Actionbar中的颜色,使用 ActionBar Generator,将所有文件复制并粘贴到res文件夹中,在Android.manifest文件中更改主题即可。


1
+1,我发现使其工作的唯一方法确实是使用样式生成器。如果您不想将其创建的数十个文件全部添加到项目中,请查看此链接:https://dev59.com/AWIk5IYBdhLWcg3wBqGW#20077381。 - Jonik
5
虽然解决了问题,但这并没有回答如何确切地做到这一点。 - Nlinscott

17
如果你看到这篇文章,可能是因为之前的答案都没有解决你基于Holo Dark主题的问题。
Holo Dark在PopupMenus中使用额外的包装器,所以在执行Jonik建议的之后,你需要在'xml'文件中添加以下样式:
<style name="PopupWrapper" parent="@android:style/Theme.Holo">
    <item name="android:popupMenuStyle">@style/YourPopupMenu</item>
</style>

然后在您的主题块中引用它:
<style name="Your.cool.Theme" parent="@android:style/Theme.Holo">
    .
    .
    .
    <item name="android:actionBarWidgetTheme">@style/PopupWrapper</item>
</style>

就是这样!


哦,太遗憾了,这是一个相当详尽的解释 :( - rupps
难道真的没有更简单的方法吗?... 目前在API28中,除了这种疯狂的方式定义操作栏颜色之外,还没有其他系统吗? - Bronz
哦,那个回答已经四年了!ActionBar现在已经被弃用了,使用ToolBar可以设置任何你想要的颜色。唯一的问题是弹出菜单的背景,我不知道情况是否有所改善,但这只是一个样式问题,不会很麻烦吧? - rupps

15

我简单的技巧,可改变弹出菜单/选项菜单中背景颜色和文本颜色。

<style name="CustomActionBarTheme"
       parent="@android:style/Theme.Holo">
    <item name="android:popupMenuStyle">@style/MyPopupMenu</item>
    <item name="android:itemTextAppearance">@style/TextAppearance</item>
</style>
<!-- Popup Menu Background Color styles -->
<style name="MyPopupMenu" 
       parent="@android:style/Widget.Holo.ListPopupWindow">
    <item name="android:popupBackground">@color/Your_color_for_background</item> 
</style>
<!-- Popup Menu Text Color styles -->
<style name="TextAppearance">
    <item name="android:textColor">@color/Your_color_for_text</item>
</style>

6

在您的应用主题中,您可以设置android:itemBackground属性以更改操作菜单的颜色。

例如:

<style name="AppThemeDark" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="colorPrimary">@color/drk_colorPrimary</item>
        <item name="colorPrimaryDark">@color/drk_colorPrimaryDark</item>
        <item name="colorAccent">@color/drk_colorAccent</item>
        <item name="actionBarStyle">@style/NoTitle</item>
        <item name="windowNoTitle">true</item>
        <item name="android:textColor">@color/white</item>

        <!-- THIS IS WHERE YOU CHANGE THE COLOR -->
        <item name="android:itemBackground">@color/drk_colorPrimary</item>
</style>


1
请使用 <item name="android:colorBackground">@color/colorAppWhite</item>,否则子菜单标题将不会改变。 - Eugene Kartoyev

4
快速的方式!
styles.xml

<style name="popupTheme" parent="Theme.AppCompat.Light">

    <item name="android:background">@color/colorBackground</item>
    <item name="android:textColor">@color/colorItem</item>

</style>

然后将这些特定的样式添加到您的AppTheme样式中。
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    ...
    <item name="popupTheme">@style/popupTheme</item>
</style>

完成!


不要使用android:background,而是使用android:colorBackground - tmm1

4

我也遇到了同样的问题,最终找到了简单的解决方案。只需要在操作栏样式中添加一行代码。

<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar">
    <item name="android:textColorPrimary">@color/colorAccent</item>
    <item name="android:colorBackground">@color/colorAppWhite</item>
</style>

"

"android:colorBackground"足以改变选项菜单的背景

"

3
您可以按照以下方式在Overflow MenuItem中应用样式和主题。Overflow菜单是ListView,因此我们可以根据ListView应用主题。
在styles.xml中应用以下代码。
<style name="AppTheme" parent="@android:style/Theme.Holo.Light">
<item name="android:dropDownListViewStyle">@style/PopupMenuListView</item>
        <item name="android:actionBarWidgetTheme">@style/PopupMenuTextView</item>
        <item name="android:popupMenuStyle">@style/PopupMenu</item>
        <item name="android:listPreferredItemHeightSmall">40dp</item>
</style>

<!-- Change Overflow Menu ListView Divider Property -->
    <style name="PopupMenuListView" parent="@android:style/Widget.Holo.ListView.DropDown">
        <item name="android:divider">@color/app_navigation_divider</item>
        <item name="android:dividerHeight">1sp</item>
        <item name="android:listSelector">@drawable/list_selector</item>
    </style>

    <!-- Change Overflow Menu ListView Text Size and Text Size -->
    <style name="PopupMenuTextView" parent="@android:style/Widget.Holo.Light.TextView">
        <item name="android:textColor">@color/app_white</item>
        <item name="android:textStyle">normal</item>
        <item name="android:textSize">18sp</item>
        <item name="android:drawablePadding">25dp</item>
        <item name="android:drawableRight">@drawable/navigation_arrow_selector</item>
    </style>

    <!-- Change Overflow Menu Background -->
    <style name="PopupMenu" parent="android:Widget.Holo.Light.ListPopupWindow">
        <item name="android:popupBackground">@drawable/menu_overflow_bg</item>
    </style>

2
请将以下内容添加到您的Styles.xml中。
<style name="Custom_Theme" parent="Theme.AppCompat.Light.DarkActionBar">

    <item name="android:itemBackground">@color/white</item>
    <item name="android:textColor">@color/colorPrimaryDark</item>

</style>

只需在activity_main.xml中更改主题。

android:theme="@style/Custom_Theme"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接