В старших SDK, таких как 33, PopupMenu с иконками отображается неправильно: Неверное всплывающее меню с иконками
Я не знаю, что не так.
Я создал его следующим образом:
//init the wrapper with style
Context wrapper = new ContextThemeWrapper(anchor.getContext(), R.style.MyPopupStyle);
//init the popup
PopupMenu popup = new PopupMenu(wrapper, anchor);
/* The below code in try catch is responsible to display icons*/
if (isWithIcons) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
popup.setForceShowIcon(true);
} else {
try {
Field[] fields = popup.getClass().getDeclaredFields();
for (Field field : fields) {
if ("mPopup".equals(field.getName())) {
field.setAccessible(true);
Object menuPopupHelper = field.get(popup);
assert menuPopupHelper != null;
Class<?> classPopupHelper = Class.forName(menuPopupHelper.getClass().getName());
Method setForceIcons = classPopupHelper.getMethod("setForceShowIcon", boolean.class);
setForceIcons.invoke(menuPopupHelper, true);
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
//inflate menu
popup.getMenuInflater().inflate(menu, popup.getMenu());
popup.show();
Пробовал с SDK 23 и там отображается корректно: Правильное PopupMenu с иконками
Следующий пост сработал для меня: https://stackoverflow.com/a/41666520/18030070
Чтобы центрировать изображение по вертикали, я использовал этот класс: https://stackoverflow.com/a/38788432/18030070
/**
* method responsible to show popup menu
*
* @param anchor is a view where the popup will be shown
* @param isWithIcons flag to check if icons to be shown or not
* @param menu menu items for popup menu
*/
public static PopupMenu showPopupMenu(View anchor, boolean isWithIcons, @MenuRes int menu) {
//init the wrapper with style
Context wrapper = new ContextThemeWrapper(anchor.getContext(), R.style.MyPopupStyle);
//init the popup
PopupMenu popupMenu = new PopupMenu(wrapper, anchor);
//inflate menu
popupMenu.getMenuInflater().inflate(menu, popupMenu.getMenu());
/* The below code in try catch is responsible to display icons*/
if (isWithIcons) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
insertMenuItemIcons(anchor.getContext(), popupMenu);
} else {
try {
Field[] fields = popupMenu.getClass().getDeclaredFields();
for (Field field : fields) {
if ("mPopup".equals(field.getName())) {
field.setAccessible(true);
Object menuPopupHelper = field.get(popupMenu);
assert menuPopupHelper != null;
Class<?> classPopupHelper = Class.forName(menuPopupHelper.getClass().getName());
Method setForceIcons = classPopupHelper.getMethod("setForceShowIcon", boolean.class);
setForceIcons.invoke(menuPopupHelper, true);
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
return popupMenu;
}
Почему бы просто не использовать всплывающее окно? Это очень просто.