更改弹出菜单背景颜色

Change Popup menu background color

NOTE: I have searched for an hour and tried all solutions already provided by Whosebug.

我正在研究主题叠加。我制作了一个示例应用程序,它会在单击操作栏图标时打开一个弹出菜单。这是我的 styles.xml

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>

    </style>

    <style name="AppTheme.NoActionBar">
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
    </style>



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

    <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Dark">
        <!-- added all to see which one will work.-->
        <item name="android:popupMenuStyle">@style/PopupMenu</item>
        <item name="android:itemBackground">@color/colorAccent</item>
        <item name="android:colorBackground">@color/colorAccent</item>

    </style>

    <style name="PopupMenu" parent="@android:style/Widget.PopupMenu">
        <item name="android:popupBackground">@color/colorAccent</item>
    </style>

</resources>

这是我的工具栏样式。

   <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay"/>

    </android.support.design.widget.AppBarLayout>

我已将 popupTheme 设置为我 styles.xml 中的那个。现在我想改变弹出菜单的背景颜色,目前是白色。

这是代码。

 @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        if(item.getItemId() == R.id.standard_menu){
            showPopupMenu(item);
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    private void showPopupMenu(MenuItem item) {
        PopupMenu p = new PopupMenu(this, findViewById(item.getItemId()));
        p.inflate(R.menu.pop_menu);
        p.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem item) {
                Toast.makeText(MainActivity.this, "clicked.", Toast.LENGTH_SHORT).show();
                return true;
            }
        });
        p.show();
    }

将 popupMenu 样式添加到您的 AppTheme:

<style name="AppTheme" parent="android:Theme.Light">
    <item name="android:popupMenuStyle">@style/PopupMenu</item>
</style>

<style name="PopupMenu" parent="@android:style/Widget.PopupMenu">
    <item name="android:popupBackground">@android:color/white</item>
</style>

manifest.xml:

 <application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
.............
</application>

我希望它会起作用。

这对我有用

<item name="android:itemBackground">@color/primary</item>

将其插入到您的主要样式中 我希望这对你有用

尝试像这样在 PopupOverlay 中使用 colorPrimary

<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" >
    <item name="colorPrimary">@color/blue_ivy</item>
</style>

我对接受的答案不满意,因为它并没有真正解释为什么没有应用 OPs 自定义弹出样式——不仅是背景,还有文本颜色之类的东西——所以我做了我自己的实验。

重要的是要注意 Toolbar 创建的弹出窗口(当它有菜单项时)和使用 PopupMenu 自己显示的弹出窗口之间存在差异。这些由不同的主题属性控制。另外,请注意有两个 PopupMenu 类:android.widget.PopupMenu, and android.support.v7.widget.PopupMenu.

您需要设置样式的主题属性 PopupMenu 您明确显示的是 android:popupMenuStylepopupMenuStyle。您有几个选项可以正确应用您的自定义样式:

(1) 在activity(或app)的主题中使用android:popupMenuStyle

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <!-- if using android.widget.PopupMenu -->
    <item name="android:popupMenuStyle">@style/PopupMenu</item>
    <!-- if using android.support.v7.widget.PopupMenu -->
    <item name="popupMenuStyle">@style/PopupMenu</item>
</style/>

<style name="PopupMenu" parent="ThemeOverlay.AppCompat.Dark">
    <item name="android:popupBackground">@color/popupBackground</item>
</style>

PopupMenu popup = new PopupMenu(this, anchorView);

请注意,这不需要在您的布局文件中添加任何额外内容。

(2) 使用 ContextThemeWrapper

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <!-- nothing special -->
</style/>

<style name="CustomPopupTheme" parent="ThemeOverlay.AppCompat.Dark">
    <!-- if using android.widget.PopupMenu -->
    <item name="android:popupMenuStyle">@style/PopupMenu</item>
    <!-- if using android.support.v7.widget.PopupMenu -->
    <item name="popupMenuStyle">@style/PopupMenu</item>
</style>

<style name="PopupMenu" parent="ThemeOverlay.AppCompat.Dark">
    <item name="android:popupBackground">@color/popupBackground</item>
</style>

ContextThemeWrapper ctw = new ContextThemeWrapper(this, R.style.CustomPopupTheme);
PopupMenu popup = new PopupMenu(ctw, anchorView);

注意在构造 ContextThemeWrapper 时如何不直接使用 R.style.PopupMenu。这似乎有点迂回,但如果您想将弹出窗口主题与 activity 或应用程序主题分开(例如,也许只有某些弹出窗口需要您的特殊主题),这很有用。

(3) 使用你的 AppBarLayout 的语境

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <!-- nothing special -->
</style/>

<style name="AppBarOverlay" parent="ThemeOverlay.AppCompat.Light">
    <!-- if using android.widget.PopupMenu -->
    <item name="android:popupMenuStyle">@style/PopupMenu</item>
    <!-- if using android.support.v7.widget.PopupMenu -->
    <item name="popupMenuStyle">@style/PopupMenu</item>
</style>

<style name="PopupMenu" parent="ThemeOverlay.AppCompat.Dark">
    <item name="android:popupBackground">@color/popupBackground</item>
</style>

<style name="PopupOverlay" parent="ThemeOverlay.AppCompat.Dark">
    <!-- changes the background of the Toolbar's popup -->
    <item name="android:colorBackground">@color/popupBackground</item>
</style>


<android.support.design.widget.AppBarLayout
    android:id="@+id/appbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:theme="@style/AppBarOverlay">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        app:popupTheme="@style/PopupOverlay"/>

</android.support.design.widget.AppBarLayout>


AppBarLayout appBar = (AppBarLayout) findViewById(R.id.app_bar);
PopupMenu popup = new PopupMenu(appBar.getContext(), anchorView);

由于您已经有 AppBar 的主题覆盖,您可以使用它来保存弹出主题引用。这也适用于工具栏的上下文,至少考虑到当前布局,但请注意 app:popupTheme 在这里实际上并不相关,因为它影响 Toolbar 的弹出窗口而不是您的 PopupMenu。另请注意这与上面的选项 2 有何相似之处,这应该会让您了解 android:theme 属性在幕后是如何工作的 ;)

在我的实验中,android:itemBackground 只有在我用它代替 PopupOverlay 样式中的 android:colorBackground 时才起作用。但是,最好使用 android:colorBackground,因为这会改变弹出窗口的 window 颜色,保留圆角和项目的可选项目 highlight/ripple。

使用 "popupMenuStyle" 支持 v7 库的 PopupMenu,以及 使用 "android:popupMenuStyle" 用于常规 PopupMenu

<style name="YOURSTYLE" parent="Widget.AppCompat.PopupMenu">
    <item name="android:textColor">@android:color/white</item>
    <item name="android:itemBackground">@android:color/holo_red_light</item>
</style>

Context wrapper = new ContextThemeWrapper(this, R.style.YOURSTYLE);
PopupMenu popup = new PopupMenu(wrapper, view);

可能对你有帮助

None 以上解决方案对我有用,所以这就是我修复它的方法:

首先为Activity制作一个新的Theme,然后:

<style name="Theme.YourTheme" parent="Theme.AppCompat">
    <item name="android:itemBackground">@color/white</item>
    <item name="android:textColor">@color/black</item>
</style>
  1. 使项目的背景变白

    <item name="android:itemBackground">@color/white</item>
    
  2. 为了对抗使文本颜色变黑

    <item name="android:textColor">@color/black</item>
    

最后,通过 Manifest 将主题应用到您的 Activity:

    <activity android:name=".YourActivity"
        android:theme="@style/Theme.YourTheme"/>

试试看

<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light">
        <item name="android:colorBackground">@color/white</item>
        <item name="android:textColor">@color/grey_900</item>
    </style>

使用 AppCompat 工具栏中的 popupTheme

 <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:popupTheme="@style/MyTheme"/>

风格:

  <style name="MyTheme" parent="ThemeOverlay.AppCompat.Light">
    <item name="android:colorBackground">@color/colorPrimary</item>
    <item name="android:textColor">@color/white</item>
</style>

希望它能奏效。

我做到了请检查是否有人也有问题将其添加到样式中

 <style name="CustomPopupTheme" parent="ThemeOverlay.AppCompat.Dark">
    <!-- if using android.widget.PopupMenu -->
    <item name="android:popupMenuStyle">@style/PopupMenu</item>
    <!-- if using android.support.v7.widget.PopupMenu -->
    <item name="popupMenuStyle">@style/PopupMenu</item>
</style>

<style name="PopupMenu" parent="ThemeOverlay.AppCompat.Dark">
    <item name="android:popupBackground">@color/appGreenColor</item>
</style>

弹出菜单的代码是

 private void openPopMenuList(View view) {
    //custom background COlor view
    PopupMenu popup = new PopupMenu(new ContextThemeWrapper(getActivity(), R.style.CustomPopupTheme), view);
    try {
        // Reflection apis to enforce show icon
        Field[] fields = popup.getClass().getDeclaredFields();
        for (Field field : fields) {
            if (field.getName().equals( POPUP_CONSTANT )) {
                field.setAccessible( true );
                Object menuPopupHelper = field.get( popup );
                Class<?> classPopupHelper = Class.forName( menuPopupHelper.getClass().getName() );
                Method setForceIcons = classPopupHelper.getMethod( POPUP_FORCE_SHOW_ICON, boolean.class );
                setForceIcons.invoke( menuPopupHelper, true );
                break;
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    popup.getMenuInflater().inflate( R.menu.pop_up_menu, popup.getMenu() );
    popup.setOnMenuItemClickListener( this );
    popup.show();


}

下面是弹出菜单项

<?xml version="1.0" encoding="utf-8"?>

<item
    android:id="@+id/share_popmenu"
    android:icon="@drawable/menu_share"
    android:title="@string/share_with_friends" />


<item
    android:id="@+id/askdelete_popmenu"
    android:icon="@drawable/menu_delete"
    android:title="Ask For Delete" />

要删除在 AndroidX 中添加的边距:

PopupMenu popup = new PopupMenu(this, my_button, 0, 0, 0);

There is no need to do changes in ANDROIDMAINFEST.xml

thank to shekhar's answer##

checkout this

you can achieve it by this in fragment or in activity by provideing or masking with it custom theme and after making the custom theme you have to pass that context to the popup menu. first create popup menu layout in menu

<?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/remove"
        android:title="Remove downloads"

        />
</menu>

second style it in style.xml

 <style name="CustomPopUpStyle" parent="Widget.AppCompat.PopupMenu">
    <item name="android:textColor">@android:color/white</item>
    <item name="android:itemBackground">@color/bgColor</item>
</style>
 

method

 private fun showPopupMenu(context: Context, view: View) {
        var wrapper: Context =  ContextThemeWrapper(context, R.style.CustomPopUpStyle)
        val popup = PopupMenu(wrapper, view)
        popup.inflate(R.menu.popup_menu)
        popup.setOnMenuItemClickListener(PopupMenu.OnMenuItemClickListener { item: MenuItem? ->
            when (item!!.itemId) {
                R.id.remove -> {
                    Toast.makeText(context, item.title, Toast.LENGTH_SHORT).show()
                }
            }

            true
        })

        popup.show()
    }

lastly initialization

 showPopupMenu(holder.itemView.context, holder.viewDataBinding.more)

and this i did in adapter of recyclerview which is in fragment

hope you liked it.

the code is self explanatory too.