Change Popup menu background color
Asked Answered
N

12

17

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

I am studying theme overlays. I have made a sample app, which opens a popup menu on clicking an action bar icon. Here is my 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>

and here is my toolbar style.

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

I have set the popupTheme to the one I have in my styles.xml. Now I want to change the background color of popup menu, which is currently white.

enter image description here

Here is the code.

 @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();
    }
Neysa answered 18/11, 2016 at 7:31 Comment(8)
Have you tried <item name="popupMenuStyle">@style/PopupMenu</item>?Exigible
Yes. Doesn't work.Neysa
see here : silverbaytech.com/2013/05/27/…Dextro
@ManikandanK why should I use Theme.Sherlock? It's deprecated.Neysa
please refer the here : grokkingandroid.com/migrating-actionbarsherlock-actionbarcompatDextro
do you even read what you have shared?Neysa
try this style <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" /> so with the use of this may also change the popup background.Alburga
Which PopupMenu are you using? android.widget.PopupMenu or android.support.v7.widget.PopupMenu?Exigible
E
48

I wasn't satisfied with the accepted answer since it doesn't really explain why the OPs custom popup style isn't being applied--not just the background, but also things like the text color--so I did my own experimentation.

It's important to note there is a difference between the popup created by the Toolbar (when it has menu items) and showing one yourself with PopupMenu. These are governed by different theme attributes. Also, be aware there are two PopupMenu classes: android.widget.PopupMenu, and android.support.v7.widget.PopupMenu.

The theme attribute you need to style PopupMenus you show explicitly is android:popupMenuStyle or popupMenuStyle. You have a few options to achieve proper application of your custom style:

(1) Use android:popupMenuStyle in the theme of the activity (or app)

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

Note this requires nothing extra in your layout file.

(2) Use a 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);

Note how this doesn't use R.style.PopupMenu directly when constructing the ContextThemeWrapper. This seems a bit roundabout, but it's useful if you want to keep the popup theme separated from activity or app themes (perhaps only some popups need your special theme, for example).

(3) Use your AppBarLayout's Context

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

Since you already have a theme overlay for the AppBar, you can use it to hold your popup theme references. This would also work with the Toolbar's context, at least given the current layout, although note that app:popupTheme is not actually relevant here since it affects the Toolbar's popup and not your PopupMenu. Also note how similar this is to option 2 above, which should clue you in to how the android:theme attribute works under the hood ;)

In my experiments, android:itemBackground only worked when I used it in place of android:colorBackground in the PopupOverlay style. However, it's better to use android:colorBackground because that will change the popup's window color, leaving the rounded corners and the selectable item highlight/ripple of the items intact.

Exigible answered 18/11, 2016 at 18:49 Comment(1)
This is the answer I've been looking all over the web for, it was of course on the last page of the internet! lol. Thanks!Mckinnon
V
7
<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);

May be its helps you

Vanlandingham answered 25/4, 2018 at 9:3 Comment(0)
C
4

i did it pls check if anybody have problem too add this to 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>

and the code of popmenu is

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


}

and the below is popmenu items

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

Correspondent answered 8/6, 2020 at 8:57 Comment(0)
D
3

This worked for me

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

Insert that into your main style I hope this works for you

Denoting answered 18/11, 2016 at 8:4 Comment(2)
Yes. It works but why other options are not working?Neysa
I'm confused. The image in the OP suggests that the entire popup style is not being applied. PopupOverlay extends ThemeOverlay.AppCompat.Dark, so the text color should be light, but clearly its not. This might solve for just the background of the popup, but doesn't really answer why the custom style defined isn't being applied.Exigible
J
2

use "popupMenuStyle" for PopupMenu in support v7 library, and use "android:popupMenuStyle" for regular PopupMenu

Janeejaneen answered 20/8, 2017 at 7:32 Comment(0)
P
2

Try it out

<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light">
        <item name="android:colorBackground">@color/white</item>
        <item name="android:textColor">@color/grey_900</item>
    </style>
Parturifacient answered 14/9, 2018 at 13:30 Comment(0)
T
1

None of the above solutions worked for me, so this is how I fixed it:

First of all make a new Theme for the Activity, and:

<style name="Theme.YourTheme" parent="Theme.AppCompat">
    <item name="android:itemBackground">@color/white</item>
    <item name="android:textColor">@color/black</item>
</style>
  1. To make the background of items white

    <item name="android:itemBackground">@color/white</item>
    
  2. To counter make the text color black

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

Lastly, apply the theme to your Activity via Manifest:

    <activity android:name=".YourActivity"
        android:theme="@style/Theme.YourTheme"/>
Teleology answered 7/5, 2018 at 11:56 Comment(0)
P
1

To remove the margin that gets added in AndroidX:

PopupMenu popup = new PopupMenu(this, my_button, 0, 0, 0);
Phrase answered 18/2, 2021 at 4:48 Comment(0)
F
1

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.

Fennel answered 3/12, 2021 at 6:46 Comment(1)
As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.Karalee
D
0

Add popupMenu style to ur 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>

i hope it will work.

Dextro answered 18/11, 2016 at 7:48 Comment(0)
O
0

try to use colorPrimary inside PopupOverlay like this

<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" >
    <item name="colorPrimary">@color/blue_ivy</item>
</style>
Omegaomelet answered 18/11, 2016 at 8:13 Comment(0)
C
0

Use popupTheme from AppCompat toolbar

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

In Style :

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

Hope it will work.

Catboat answered 23/6, 2019 at 8:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.