web-dev-qa-db-fra.com

Est-il possible d'afficher des icônes dans un PopupMenu?

J'aime vraiment le nouveau PopupMenu que nous avons dans la version 3.0, mais je ne peux simplement pas afficher d'icônes à côté des éléments de menu qu'il contient. Je gonfle le menu à partir du fichier .xml ci-dessous:

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

Avec ce code:

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

Je ne parviens pas à faire apparaître les icônes. Quelque chose me manque-t-il?

45

Si vous voulez être un peu aventureux, consultez le code source de Google pour PopupMenu. Créez votre propre classe, à savoir MyPopupMenu, identique à la classe PopupMenu de Google, mais apportez une légère modification.

Dans le constructeur de 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

}

utilisez la méthode setForceShowIcon pour le forcer à afficher l'icône. Vous pouvez également simplement exposer une méthode publique pour définir cet indicateur en fonction de vos besoins.

28
Robert

Contribution à la solution fournie par Gaelan Bolger . Utilisez ce code si vous obtenez une "IllegalAccessException: accès au champ non autorisé".

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

texte

67
dgtale

J'ai pu montrer les icônes en utilisant la réflexion. Ce n'est peut-être pas la solution la plus élégante, mais ça marche.

            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();
            }
18
GaBo

Nous pouvons utiliser le modèle de sous-menu. Donc, nous n’avons pas besoin d’écrire une méthode pour afficher le menu contextuel, elle sera affichée automatiquement. Regarde:

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>

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

Le résultat est:

 Result

16
Sarvar Nishonboev

avant d'utiliser la méthode popup.show (), créez une instance de MenuPopupHelper et appelez la méthode setForceShowIcon (true), comme ceci

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

    }
11
Mao

Le moyen le plus simple que j'ai trouvé est d'utiliser MenuBuilder et 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

7
Ajay Sivan

J'ai trouvé une solution native pour cela, en utilisant 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();
}

Usage

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

                }
            });
        }
    });
}
6
Ilya Gazman

PopupMenu n'affichera pas les icônes. Vous pouvez utiliser un ActionBar. 

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

3
SpearHend

Certaines des solutions ci-dessus fonctionnent avec le hack de réflexion,

Juste pour partager ceci: j'ai récemment rencontré les mêmes problèmes, mais je voulais aussi créer une chose plus personnalisée (ajouter une vue personnalisée dans le menu). J'ai donc créé la bibliothèque suivante.

https://github.com/shehabic/Droppy

2
Shehabic

En utilisant la réflexion et sans avoir besoin d'utiliser MenuPopupHelper, vous pouvez ajouter

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

avant de gonfler le menu

1
Nonos