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?
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.
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
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();
}
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:
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) {
}
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>
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();
}
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) {
}
});
}
});
}
PopupMenu n'affichera pas les icônes. Vous pouvez utiliser un ActionBar.
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.
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