68

Of course we are dealing here with SDK 11 and above.

I intend to do something similar to this: enter image description here

Next to each item in that PopupMenu, I would like to place an icon.

I created an XML file and placed it in /menu:

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

    <item
        android:id="@+id/action_one"
        android:title="Sync"
        android:icon="@android:drawable/ic_popup_sync"
        />

    <item
        android:id="@+id/action_two"
        android:title="About"
        android:icon="@android:drawable/ic_dialog_info"
        />
</menu>

As you noticed, in the xml file I am defining the icons I want, however, when the popup menu shows, it is showing them without the icons. What should I do to make those 2 icons appear?

Alex
  • 1,551
  • 3
  • 17
  • 30
  • I think that's the easiest way to implement such feature: http://stackoverflow.com/a/33487225/4890659 – Anton Nov 02 '15 at 21:27

12 Answers12

100

This way works if you're using AppCompat v7. It's a little hacky but significantly better than using reflection and lets you still use the core Android PopupMenu:

PopupMenu menu = new PopupMenu(getContext(), overflowImageView);
menu.inflate(R.menu.popup);
menu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { ... });

MenuPopupHelper menuHelper = new MenuPopupHelper(getContext(), (MenuBuilder) menu.getMenu(), overflowImageView);
menuHelper.setForceShowIcon(true);
menuHelper.show();

res/menu/popup.xml

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

    <item android:id="@+id/menu_share_location"
        android:title="@string/share_location"
        android:icon="@drawable/ic_share_black_24dp"/>

</menu>


This results in the popup menu using the icon that is defined in your menu resource file:

enter image description here

Stephen Kidson
  • 2,701
  • 3
  • 18
  • 20
  • Where you put the icon in this example? – Dan Ponce Sep 23 '16 at 17:28
  • I've updated the example with a sample popup.xml and a screenshot – Stephen Kidson Sep 23 '16 at 21:06
  • It's quite simple and working like Champ, Good work. Works in app API version as well. – Mitesh Jain Oct 07 '16 at 06:55
  • 2
    Great solution! Small tip: You don't even need to create a `PopupMenu` instance as you did. Just create a new `MenuBuilder()` inflate the menu into it and pass it to the helper. – david.schreiber Oct 07 '16 at 11:50
  • 1
    Good catch @david.schreiber - I pulled this from my code where I removed some lines. I actually create the PopupMenu so I can use `setonMenuItemClickListener()`. Going to add this to the example as I'm sure most developers would want to know when their menu item is clicked! – Stephen Kidson Nov 14 '16 at 22:59
  • Android Studio is asking me for this: `@SuppressLint("RestrictedApi")` – IgniteCoders Nov 06 '17 at 05:30
  • 1
    Anyway, i cant find the need class for that. It's throwing this exception: `java.lang.ClassCastException: com.android.internal.view.menu.MenuBuilder cannot be cast to android.support.v7.view.menu.MenuBuilder` – IgniteCoders Nov 06 '17 at 05:38
  • 2
    @IgniteCoders Use the MenuBuilder from the v7 support library. So change your imports. – Jeffrey Nov 08 '17 at 15:32
  • 2
    @IgniteCoders To fix the ClassCastException, replace `import android.widget.PopupMenu;` with `import android.support.v7.widget.PopupMenu;` – Mr-IDE Aug 16 '18 at 16:29
  • Sounded promising but I couldn't get this to work myself - went down the rabbit hole for 45 mins and failed - then I ended up using ListPopupWindow which worked fine – davidfrancis Jul 25 '20 at 11:32
  • 1
    This also works if you have migrated to the `androidx` support libraries: `androidx.appcompat.widget.PopupMenu`. – Tjaart Nov 08 '20 at 23:45
  • A similar solution is actually suggested in https://www.material.io/components/menus/android#adding-icons-on-popup-menus however the warning is that this API is restricted and might not work in the future. – antanas_sepikas Jan 14 '21 at 08:35
43

I would implement it otherwise:

Create a PopUpWindow layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/llSortChangePopup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/sort_popup_background"
android:orientation="vertical" >

<TextView
    android:id="@+id/tvDistance"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/distance"
    android:layout_weight="1.0"
    android:layout_marginLeft="20dp"
    android:paddingTop="5dp"
    android:gravity="center_vertical"
    android:textColor="@color/my_darker_gray" />

<ImageView
    android:layout_marginLeft="11dp"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/sort_popup_devider" 
    android:contentDescription="@drawable/sort_popup_devider"/>

<TextView
    android:id="@+id/tvPriority"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/priority"
    android:layout_weight="1.0"
    android:layout_marginLeft="20dp"
    android:gravity="center_vertical"
    android:clickable="true"
    android:onClick="popupSortOnClick"
    android:textColor="@color/my_black" />


<ImageView
    android:layout_marginLeft="11dp"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/sort_popup_devider" 
    android:contentDescription="@drawable/sort_popup_devider"/>

<TextView
    android:id="@+id/tvTime"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/time"
    android:layout_weight="1.0"
    android:layout_marginLeft="20dp"
    android:gravity="center_vertical"
    android:clickable="true"
    android:onClick="popupSortOnClick"
    android:textColor="@color/my_black" />

<ImageView
    android:layout_marginLeft="11dp"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/sort_popup_devider" 
    android:contentDescription="@drawable/sort_popup_devider"/>

<TextView
    android:id="@+id/tvStatus"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/status"
    android:layout_weight="1.0"
    android:layout_marginLeft="20dp"
    android:gravity="center_vertical"
    android:textColor="@color/my_black" 
    android:clickable="true"
    android:onClick="popupSortOnClick"
    android:paddingBottom="10dp"/>

 </LinearLayout>

and also create the PopUpWindow in your Activity:

    // The method that displays the popup.
private void showStatusPopup(final Activity context, Point p) {

   // Inflate the popup_layout.xml
   LinearLayout viewGroup = (LinearLayout) context.findViewById(R.id.llStatusChangePopup);
   LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
   View layout = layoutInflater.inflate(R.layout.status_popup_layout, null);

   // Creating the PopupWindow
   changeStatusPopUp = new PopupWindow(context);
   changeStatusPopUp.setContentView(layout);
   changeStatusPopUp.setWidth(LinearLayout.LayoutParams.WRAP_CONTENT);
   changeStatusPopUp.setHeight(LinearLayout.LayoutParams.WRAP_CONTENT);
   changeStatusPopUp.setFocusable(true);

   // Some offset to align the popup a bit to the left, and a bit down, relative to button's position.
   int OFFSET_X = -20;
   int OFFSET_Y = 50;

   //Clear the default translucent background
   changeStatusPopUp.setBackgroundDrawable(new BitmapDrawable());

   // Displaying the popup at the specified location, + offsets.
   changeStatusPopUp.showAtLocation(layout, Gravity.NO_GRAVITY, p.x + OFFSET_X, p.y + OFFSET_Y);
}

finally pop it up onClick of a button or anything else:

 imTaskStatusButton.setOnClickListener(new OnClickListener() 
        {
            public void onClick(View v) 
            {
                 int[] location = new int[2];
                 currentRowId = position;
                 currentRow = v;    
                 // Get the x, y location and store it in the location[] array
                 // location[0] = x, location[1] = y.
                 v.getLocationOnScreen(location);

                 //Initialize the Point with x, and y positions
                 point = new Point();
                 point.x = location[0];
                 point.y = location[1];
                 showStatusPopup(TasksListActivity.this, point);
            }
        });

A Good example for PopUpWindow:

http://androidresearch.wordpress.com/2012/05/06/how-to-create-popups-in-android/

Blane Townsend
  • 2,308
  • 5
  • 36
  • 50
Emil Adz
  • 38,699
  • 35
  • 127
  • 177
  • 4
    thanks Emil for your reply. However, I've found a way once to override the current PopupMenu class, with a method called setforceicon..(true) or something like that.. I forgot – Alex Mar 16 '13 at 21:53
  • No i didn't figure it out, i'm asking you if you already know something like that... I'm still searching for a solution! haha – Alex Mar 16 '13 at 21:58
  • if I am not mistaken when you define the menu XML you want the menu to pop up on the press of the hardware menu button right? – Emil Adz Mar 16 '13 at 22:01
  • No I want it to popup on the press of a `View` in the corner, just like the "Google Maps" app shown above. – Alex Mar 16 '13 at 22:03
  • and is it working right now? does it pop up when you press the view in the desired location? – Emil Adz Mar 16 '13 at 22:05
  • Yes it popups! but the thing is that it doesn't show the icons. And yes it popups in the desired location under my View. I just want the icons to show that's all :) – Alex Mar 16 '13 at 22:05
  • then try this link: http://stackoverflow.com/questions/2999866/how-can-i-create-an-android-menu-item-using-android-setting-icon – Emil Adz Mar 16 '13 at 22:06
  • Unfortunately, it's not what i'm searching for... – Alex Mar 16 '13 at 22:11
  • maybe what you are looking for is not in the menu object, for what I know you can set only a limited number of icons to the menu items and I have no idea how it's control in in the later versions.Have you searched in the documentation? : http://developer.android.com/guide/topics/ui/menus.html – Emil Adz Mar 16 '13 at 22:16
  • Don't you think that the one in the pic is a spinner and not a popupmenu? – Alex Mar 16 '13 at 22:35
  • actually I think it's a pop that design as I showed you... as a PopUpWindow... but maybe I'm wrong and there is another way to do that. – Emil Adz Mar 16 '13 at 22:39
  • Thanks for your time, I do appreciate your help! :) – Alex Mar 16 '13 at 22:41
  • You welcome, @JonathanHugh. Hope I was helpful ; ) – Emil Adz Mar 16 '13 at 22:43
  • What's currentRowId = position; and currentRow = v; here?? – DroidLearner Aug 23 '13 at 08:58
  • @DroidLearner, you can ignore it in this case, it's not relevant to the Popup example. – Emil Adz Aug 23 '13 at 12:30
  • What are R.id.llStatusChangePopup and R.layout.status_popup_layout? – Compaq LE2202x Aug 29 '13 at 07:40
  • R.layout.status_popup_layout is the popup layout. llStatusChangePopup is the layout in which i pop the popup. – Emil Adz Aug 29 '13 at 09:24
  • This approach worked perfectly for me. Saved a ton of time. – Rarw Jan 14 '14 at 21:39
  • @EmilAdz : what is "@drawable/sort_popup_background" ? – young_08 May 26 '16 at 06:20
  • @young_08, sort_popup_background is just a background resource image for the popup. – Emil Adz May 26 '16 at 07:26
  • @EmilAdz i as well used the above answer but i couldn't able to inflate layout . can you please help me – young_08 May 26 '16 at 07:59
  • @EmilAdz http://stackoverflow.com/questions/37455149/popmenus-with-icons – young_08 May 26 '16 at 08:12
  • How to add on click listeners to each of the text view? Every time I add it I get a null object reference error – A.S Aug 31 '18 at 07:10
  • It seems to me like while PopupMenu does dismiss when clicking outside of it PopupWindow behaves differently. How do I get it to behave the same way? – Christian Jul 15 '19 at 15:02
28

Android popup menu has a hidden method to show menu icon. Use Java reflection to enable it as below code snippet.

public static void setForceShowIcon(PopupMenu popupMenu) {
    try {
        Field[] fields = popupMenu.getClass().getDeclaredFields();
        for (Field field : fields) {
            if ("mPopup".equals(field.getName())) {
                field.setAccessible(true);
                Object menuPopupHelper = field.get(popupMenu);
                Class<?> classPopupHelper = Class.forName(menuPopupHelper
                        .getClass().getName());
                Method setForceIcons = classPopupHelper.getMethod(
                        "setForceShowIcon", boolean.class);
                setForceIcons.invoke(menuPopupHelper, true);
                break;
            }
        }
    } catch (Throwable e) {
        e.printStackTrace();
    }
}
Bao Le
  • 13,726
  • 9
  • 59
  • 67
  • 1
    For some reason this snippet does not work after I create production apk, although perfectly works in debug mode. It was a disappointing surprise for me :( . Do you have any clue of how to make it work? – Ivan Mar 25 '16 at 10:50
  • 1
    Probably, proguard changed class/field name. You should both class name and field name for PopupMenu class. – Bao Le Mar 25 '16 at 10:54
  • 1
    This solution doesnt change the width of the menu. it doesnt consider the additions of icons so the text is cropped. – AsafK May 26 '16 at 09:03
  • Works perfect with `android.support.v7.widget.PopupMenu` – Eugene Krivenja Jun 08 '16 at 09:38
25

Popup menu with icon using MenuBuilder and MenuPopupHelper

    MenuBuilder menuBuilder =new MenuBuilder(this);
    MenuInflater inflater = new MenuInflater(this);
    inflater.inflate(R.menu.menu, menuBuilder);
    MenuPopupHelper optionsMenu = new MenuPopupHelper(this, menuBuilder, view);
    optionsMenu.setForceShowIcon(true);

    // Set Item Click Listener
    menuBuilder.setCallback(new MenuBuilder.Callback() {
        @Override
        public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
            switch (item.getItemId()) {
                case R.id.opt1: // Handle option1 Click
                    return true;
                case R.id.opt2: // Handle option2 Click
                    return true;
                default:
                    return false;
            }
        }

        @Override
        public void onMenuModeChange(MenuBuilder menu) {}
    });


    // Display the menu
    optionsMenu.show();

menu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/opt1"
        android:icon="@mipmap/ic_launcher"
        android:title="option 1" />
    <item
        android:id="@+id/opt2"
        android:icon="@mipmap/ic_launcher"
        android:title="option 2" />
</menu>

enter image description here

Ajay Sivan
  • 1,895
  • 2
  • 22
  • 41
  • I want to select option1 and do something, how to achieve? – John Joe Jan 03 '17 at 08:19
  • @JohnJoe I have added the code sample to handle the menu click. – Ajay Sivan Jan 03 '17 at 09:11
  • 6
    this code show error **MenuBuilder constructor can only be called from within the same library group (groupId=com.android.support)** for `MenuBuilder`. Same kind of error shown for `MenuPopupHelper` and `setForceShowIcon` – Aashish Feb 05 '18 at 10:08
  • @Aashish This solution worked for me. I don't know why you're getting such an error. Do an error specific search that may help. I will try to figure out it. If you get the solution please share that here, that may help others. – Ajay Sivan Feb 05 '18 at 10:17
  • 6
    Aashish: add `@SuppressLint("RestrictedApi")` above the method, to get rid of the error. – lenooh Feb 15 '18 at 19:47
  • Good solution, thanks – King Of The Jungle Aug 31 '18 at 14:24
  • 2
    it was awesome and it works correctly , just remember to add `@SuppressLint("RestrictedApi")`at the start of your method . Thanks – ParSa Jul 01 '19 at 22:54
25

The MenuPopupHelper class in AppCompat has the @hide annotation. If that's a concern, or if you can't use AppCompat for whatever reason, there's another solution using a Spannable in the MenuItem title which contains both the icon and the title text.

The main steps are:

  • inflate your PopupMenu with a menu xml file
  • if any of the items have an icon, then do this for all of the items:
    • if the item doesn't have an icon, create a transparent icon. This ensures items without icons will be aligned with items with icons
    • create a SpannableStringBuilder containing the icon and title
    • set the menu item's title to the SpannableStringBuilder
    • set the menu item's icon to null, "just in case"

Pros: No reflection. Doesn't use any hidden apis. Can work with the framework PopupMenu.

Cons: More code. If you have a submenu without an icon, it will have unwanted left padding on a small screen.


Details:

First, define a size for the icon in a dimens.xml file:

<dimen name="menu_item_icon_size">24dp</dimen>

Then, some methods to move the icons defined in xml into the titles:

/**
 * Moves icons from the PopupMenu's MenuItems' icon fields into the menu title as a Spannable with the icon and title text.
 */
public static void insertMenuItemIcons(Context context, PopupMenu popupMenu) {
    Menu menu = popupMenu.getMenu();
    if (hasIcon(menu)) {
        for (int i = 0; i < menu.size(); i++) {
            insertMenuItemIcon(context, menu.getItem(i));
        }
    }
}

/**
 * @return true if the menu has at least one MenuItem with an icon.
 */
private static boolean hasIcon(Menu menu) {
    for (int i = 0; i < menu.size(); i++) {
        if (menu.getItem(i).getIcon() != null) return true;
    }
    return false;
}

/**
 * Converts the given MenuItem's title into a Spannable containing both its icon and title.
 */
private static void insertMenuItemIcon(Context context, MenuItem menuItem) {
    Drawable icon = menuItem.getIcon();

    // If there's no icon, we insert a transparent one to keep the title aligned with the items
    // which do have icons.
    if (icon == null) icon = new ColorDrawable(Color.TRANSPARENT);

    int iconSize = context.getResources().getDimensionPixelSize(R.dimen.menu_item_icon_size);
    icon.setBounds(0, 0, iconSize, iconSize);
    ImageSpan imageSpan = new ImageSpan(icon);

    // Add a space placeholder for the icon, before the title.
    SpannableStringBuilder ssb = new SpannableStringBuilder("       " + menuItem.getTitle());

    // Replace the space placeholder with the icon.
    ssb.setSpan(imageSpan, 1, 2, 0);
    menuItem.setTitle(ssb);
    // Set the icon to null just in case, on some weird devices, they've customized Android to display
    // the icon in the menu... we don't want two icons to appear.
    menuItem.setIcon(null);
}

Finally, create your PopupMenu and use the above methods before showing it:

PopupMenu popupMenu = new PopupMenu(view.getContext(), view);
popupMenu.inflate(R.menu.popup_menu);
insertMenuItemIcons(textView.getContext(), popupMenu);
popupMenu.show();

Screenshot: screenshot

Carmen
  • 1,424
  • 14
  • 17
  • 1
    Thanks for providing a solution for non-AppCompat projects. All other answers (on other questions too) don't even mention AppCompat being a requirement. – Jeffrey Nov 08 '17 at 15:43
17

You can implement this By the use of Reflection if u don`t familiar with it with the help of this awesome java advanced feature u can modify the runtime behavior of applications running in the JVM you can look at the object and perform its methods at runtime and in our case we need to modify popupMenu behavior at runtime instead of extend the core class and modify it ;) hope that help

private void showPopupMenu(View view) {
    // inflate menu
    PopupMenu popup = new PopupMenu(mcontext, view);
    MenuInflater inflater = popup.getMenuInflater();
    inflater.inflate(R.menu.main, popup.getMenu());

    Object menuHelper;
    Class[] argTypes;
    try {
        Field fMenuHelper = PopupMenu.class.getDeclaredField("mPopup");
        fMenuHelper.setAccessible(true);
        menuHelper = fMenuHelper.get(popup);
        argTypes = new Class[]{boolean.class};
        menuHelper.getClass().getDeclaredMethod("setForceShowIcon", argTypes).invoke(menuHelper, true);
    } catch (Exception e) {

    }
    popup.show();




} 
Mohamed Ayed
  • 417
  • 5
  • 7
12

list_item_menu.xml in /res/menu directory

<?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/locale"
                android:title="Localizar"
                android:icon="@mipmap/ic_en_farmacia_ico"
                app:showAsAction="always">
            </item>

            <item android:id="@+id/delete"
                android:title="Eliminar"
                android:icon="@mipmap/ic_eliminar_ico"
                app:showAsAction="always">
            </item>
    </menu>

In my activity

private void showPopupOption(View v){
    PopupMenu popup = new PopupMenu(getContext(), v);
    popup.getMenuInflater().inflate(R.menu.list_item_menu, popup.getMenu());

    popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
        public boolean onMenuItemClick(MenuItem menu_item) {
            switch (menu_item.getItemId()) {
                case R.id.locale:
                    break;
                case R.id.delete:
                    break;
            }
            return true;
        }
    });

    MenuPopupHelper menuHelper = new MenuPopupHelper(getContext(), (MenuBuilder) popup.getMenu(), v);
    menuHelper.setForceShowIcon(true);
    menuHelper.setGravity(Gravity.END);
    menuHelper.show();
}

result

popup_menu

Nathan Tuggy
  • 2,239
  • 27
  • 28
  • 36
9

Read the PopupMenu source code. We can show icon by the below code:

Field field = popupMenu.getClass().getDeclaredField("mPopup");
field.setAccessible(true);
MenuPopupHelper menuPopupHelper = (MenuPopupHelper) field.get(popupMenu);
menuPopupHelper.setForceShowIcon(true);

But MenuPopupHelper.java is in android internal package. So we should use Reflection:

    PopupMenu popupMenu = new PopupMenu(this, anchor);
    popupMenu.getMenuInflater().inflate(R.menu.process, popupMenu.getMenu());

    try {
        Field field = popupMenu.getClass().getDeclaredField("mPopup");
        field.setAccessible(true);
        Object menuPopupHelper = field.get(popupMenu);
        Class<?> cls = Class.forName("com.android.internal.view.menu.MenuPopupHelper");
        Method method = cls.getDeclaredMethod("setForceShowIcon", new Class[]{boolean.class});
        method.setAccessible(true);
        method.invoke(menuPopupHelper, new Object[]{true});
    } catch (Exception e) {
        e.printStackTrace();
    }

    popupMenu.show();
yinghuihong
  • 225
  • 2
  • 6
  • Thanks - while this method works if you use Alex's original xml menu file where he has defined the items with their associated icons, I'm concerned about the lack of control that I have been given with regards to setting the margin / padding of the drawable as those options cannot be set. I'm beginning to think using popupmenus is not such a good idea. – Simon Oct 18 '15 at 19:35
  • Now you can use [MenuPopupHelper](https://android.googlesource.com/platform/frameworks/support/+/400270d/v7/appcompat/src/android/support/v7/internal/view/menu/MenuPopupHelper.java) in v7 package to do this without reflect. – Desmond Yao Oct 08 '16 at 02:15
  • 1
    **Accessing internal APIs via reflection is not supported and may not work on all devices or in the future** warning shown. Any update to resolve it?? – Aashish Feb 05 '18 at 10:12
6

I solved my issue the simplest possible way ever, never expected such a simplicity:

In main.xml:

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

<item
    android:id="@+id/action_more"
    android:icon="@android:drawable/ic_menu_more"
    android:orderInCategory="1"
    android:showAsAction="always"
    android:title="More">
    <menu>
        <item
            android:id="@+id/action_one"
            android:icon="@android:drawable/ic_popup_sync"
            android:title="Sync"/>
        <item
            android:id="@+id/action_two"
            android:icon="@android:drawable/ic_dialog_info"
            android:title="About"/>
    </menu>
</item>

in MainActivity.java

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

That was a trick by using a submenu

Alex
  • 1,551
  • 3
  • 17
  • 30
5

If you want to display icon in popup menu, have a look at https://github.com/shehabic/Droppy , it's pretty cool and easy to use

Gintama
  • 1,073
  • 19
  • 29
  • Without using any library...Is it possible to set icons with titles in pop up menu ? – Ghanshyam Nayma Mar 29 '16 at 07:21
  • @DHAKAD Yes you can as people in this thread discussed. Or you can look at this library source to see how they can set icons and use exactly what you want. – Gintama Mar 29 '16 at 07:29
  • Actually I try to add icons simply like android:icon="@drawable/ic_menu_more" , why it doesn't work ?? – Ghanshyam Nayma Mar 29 '16 at 08:45
  • i don't try this yet http://stackoverflow.com/a/36197689/1236933. And why don't you just use the Droppy lib above, it's simple – Gintama Mar 29 '16 at 09:00
  • This is the only method that works, and is also upgrade safe. Also, the option of generating the menu programmatic is much neater than generating the menu with layouts and xml. Many thanks – Mijo Aug 26 '17 at 10:38
1

Based on @Ajay answer...here is what I did

 @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.add_task, menu);  // for the two icons in action bar
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {

            case R.id.menu:
                View menuItemView = findViewById(R.id.menu);
                MenuBuilder menuBuilder =new MenuBuilder(this);
                MenuInflater inflater = new MenuInflater(this);
                inflater.inflate(R.menu.popup, menuBuilder);
                MenuPopupHelper optionsMenu = new MenuPopupHelper(this, menuBuilder, menuItemView); 
                optionsMenu.setForceShowIcon(true);
                optionsMenu.show();

            default:
                return super.onOptionsItemSelected(item);
        }
    }

popup

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
    android:id="@+id/opt1"
    android:icon="@drawable/change_pic"
    android:title="Change Picture" />
<item
    android:id="@+id/opt2"
    android:icon="@drawable/change_pin"
    android:title="Change Password" />

    <item
        android:id="@+id/opt3"
        android:icon="@drawable/sign_out"
        android:title="Sign Out" />
</menu>

ScreenShot

enter image description here

John Joe
  • 10,340
  • 9
  • 48
  • 104
0

I was trying @Stephen Kidson's answer and @david.schereiber's suggestion, and I realized that there is no such method setOnMenuItemClickListener in MenuBuilder. Messed around with the v7's source code a little bit and I found this solution:

        MenuBuilder menuBuilder = new MenuBuilder(mContext);
        new SupportMenuInflater(mContext).inflate(R.menu.my_menu, menuBuilder);
        menuBuilder.setCallback(new MenuBuilder.Callback() {
            @Override
            public boolean onMenuItemSelected(MenuBuilder menu, MenuItem menuItem) {
                // your "setOnMenuItemClickListener" code goes here
                switch (menuItem.getItemId()) {
                    case R.id.menu_id1:
                        // do something 1
                        return true;

                    case R.id.menu_id2:
                        // do something 2
                        return true;
                }
                return false;
            }

            @Override
            public void onMenuModeChange(MenuBuilder menu) {
            }
        });
        MenuPopupHelper menuHelper = new MenuPopupHelper(mContext, menuBuilder, v);
        menuHelper.setForceShowIcon(true); // show icons!!!!!!!!
        menuHelper.show();
Leo
  • 1,423
  • 22
  • 40
  • There's a more straightforward way using the PopupMenu object my answer above instantiates: `menu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { ... });` – Stephen Kidson Nov 14 '16 at 22:56
  • I don't want to create `PopupMenu` just to inflate the menu then to get it out, with my method I can just inflate the menu directly into the MenuBuilder, I think it's better – Leo Nov 15 '16 at 02:03