Можно ли отображать значки в PopupMenu? - PullRequest
45 голосов
/ 24 июля 2011

Мне действительно нравится новое PopupMenu, которое мы получили в 3.0, но я просто не могу отображать значки рядом с пунктами меню в нем.Я надуваю меню из .xml ниже:

<item android:id="@+id/menu_delete_product"
    android:icon="@drawable/sym_action_add"
    android:title="delete"
    android:showAsAction="ifRoom|withText" />

<item android:id="@+id/menu_modify_product"
    android:icon="@drawable/sym_action_add"
    android:title="modify"
    android:showAsAction="ifRoom|withText" />

<item android:id="@+id/menu_product_details"
    android:icon="@drawable/sym_action_add"
    android:title="details"
    android:showAsAction="ifRoom|withText" />

С этим кодом:

image.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        PopupMenu pop = new PopupMenu(getActivity(), v);
        pop.getMenuInflater().inflate(R.menu.shelves_details_menu, pop.getMenu());
        pop.show();
    }
});

Я не могуполучить значки, чтобы показать, я что-то упустил?

Ответы [ 10 ]

67 голосов
/ 25 августа 2013

Вклад в решение предоставлен Gaelan Bolger.Используйте этот код, если вы получаете «IllegalAccessException: доступ к полю запрещен».

PopupMenu popup = new PopupMenu(mContext, view);

try {
    Field[] fields = popup.getClass().getDeclaredFields();
    for (Field field : fields) {
        if ("mPopup".equals(field.getName())) {
            field.setAccessible(true);
            Object menuPopupHelper = field.get(popup);
            Class<?> classPopupHelper = Class.forName(menuPopupHelper
                    .getClass().getName());
            Method setForceIcons = classPopupHelper.getMethod(
                    "setForceShowIcon", boolean.class);
            setForceIcons.invoke(menuPopupHelper, true);
            break;
        }
    }
} catch (Exception e) {
    e.printStackTrace();
}

prepareMenu(popup.getMenu());
popup.show();

text

28 голосов
/ 27 ноября 2012

Если вы хотите немного приключений, посмотрите на исходный код Google для PopupMenu. Создайте свой собственный класс, т.е. MyPopupMenu, который совпадает с классом Google PopupMenu, но внесите одно небольшое изменение.

В конструкторе PopupMenu:

public MyPopupMenu(Context context, View anchor) {
    // TODO Theme?
    mContext = context;
    mMenu = new MenuBuilder(context);
    mMenu.setCallback(this);
    mAnchor = anchor;
    mPopup = new MenuPopupHelper(context, mMenu, anchor);
    mPopup.setCallback(this);
    mPopup.setForceShowIcon(true); //ADD THIS LINE

}

используйте метод setForceShowIcon, чтобы заставить его показывать значок. Вы также можете просто выставить публичный метод для установки этого флага, в зависимости от ваших потребностей.

18 голосов
/ 28 июня 2013

Мне удалось показать значки, используя отражение. Возможно, это не самое элегантное решение, но оно работает.

            try {
                Class<?> classPopupMenu = Class.forName(popupMenu
                        .getClass().getName());
                Field mPopup = classPopupMenu.getDeclaredField("mPopup");
                mPopup.setAccessible(true);
                Object menuPopupHelper = mPopup.get(popupMenu);
                Class<?> classPopupHelper = Class.forName(menuPopupHelper
                        .getClass().getName());
                Method setForceIcons = classPopupHelper.getMethod(
                        "setForceShowIcon", boolean.class);
                setForceIcons.invoke(menuPopupHelper, true);
            } catch (Exception e) {
                e.printStackTrace();
            }
17 голосов
/ 20 ноября 2013

Мы можем использовать модель подменю.Таким образом, нам не нужно писать метод для отображения всплывающего меню, оно будет отображаться автоматически.Посмотрите:

menu.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>
</menu>

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

Результат:

Result

11 голосов
/ 18 июля 2015

перед использованием метода popup.show () создайте экземпляр MenuPopupHelper и вызовите метод setForceShowIcon (true), например,

    try {
        Field mFieldPopup=popupMenu.getClass().getDeclaredField("mPopup");
        mFieldPopup.setAccessible(true);
        MenuPopupHelper mPopup = (MenuPopupHelper) mFieldPopup.get(popupMenu);
        mPopup.setForceShowIcon(true);
    } catch (Exception e) {

    }
7 голосов
/ 28 ноября 2016

Самый простой способ, который я нашел, это использовать MenuBuilder и 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

6 голосов
/ 24 марта 2016

Я нашел для этого собственное решение, используя MenuPopupHelper.setForceShowIcon(true).

private void createMenu(int menuRes, View anchor, MenuBuilder.Callback callback) {
    Context context = anchor.getContext();

    NavigationMenu navigationMenu = new NavigationMenu(context);
    navigationMenu.setCallback(callback);

    SupportMenuInflater supportMenuInflater = new SupportMenuInflater(context);
    supportMenuInflater.inflate(menuRes, navigationMenu);

    MenuPopupHelper menuPopupHelper = new MenuPopupHelper(context, navigationMenu, anchor);
    menuPopupHelper.setForceShowIcon(true);
    menuPopupHelper.show();
}

Использование

private void initMenu(View view) {
    view.findViewById(R.id.myButton).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            createMenu(R.menu.help_menu, view, new MenuBuilder.Callback() {
                @Override
                public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
                    switch (item.getItemId()) {
                        case R.id.id1:
                            // Do something
                            break;
                        case R.id.id2:
                            // Do something
                            break;
                        case R.id.id3:
                            // Do something
                            break;
                    }
                    return true;
                }

                @Override
                public void onMenuModeChange(MenuBuilder menu) {

                }
            });
        }
    });
}
3 голосов
/ 15 мая 2012

PopupMenu не будет отображать значки.Вы можете использовать ActionBar.

http://developer.android.com/guide/topics/ui/actionbar.html

2 голосов
/ 02 марта 2015

Некоторые из приведенных выше решений будут работать с взломом отражений,

Просто поделюсь этим: я недавно сталкивался с такими же проблемами, но я также хотел создать более персонализированную вещь (добавление пользовательского представленияменю), поэтому я создал следующую библиотеку.

https://github.com/shehabic/Droppy

1 голос
/ 02 марта 2018

По линии использования отражения и без необходимости использовать MenuPopupHelper, вы можете добавить

    if (popup.getMenu() instanceof MenuBuilder) {
                //noinspection RestrictedApi
                ((MenuBuilder) popup.getMenu()).setOptionalIconsVisible(true);
            }

до надувания меню

...