[英]Popup menu with icon on Android
我的菜單 xml 代碼menu.xml :
<?xml version="1.0" encoding="utf-8"?><menu xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Single menu item
Set id, icon and Title for each menu item
-->
<item android:id="@+id/back"
android:icon="@drawable/back1"
android:showAsAction="never"
android:title="Back" />
<item android:id="@+id/My_Profile"
android:icon="@drawable/myprofile"
android:showAsAction="never"
android:title="My Profile" />
<item android:id="@+id/Job_Alert"
android:icon="@drawable/jobalert4"
android:showAsAction="never"
android:title="Job Alert !" />
<item android:id="@+id/saved_job"
android:icon="@drawable/jobapplied"
android:title="Saved Jobs"
/>
<item android:id="@+id/Logout"
android:icon="@drawable/logout"
android:title="Logout" />
</menu>
我像這樣調用菜單xml
PopupMenu popup = new PopupMenu(getBaseContext(), v);
popup.getMenuInflater().inflate(R.menu.menu, popup.getMenu());
popup.show();
但它不顯示圖標。
如何在彈出菜單上設置圖標?
您可以使用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) {}
});
optionsMenu.show();
菜單.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>
您可以通過使用 Java 反射調用隱藏方法來啟用彈出菜單的圖標,如下所示:
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();
}
}
這是因為當您使用showAsAction="never"
屬性時,默認溢出不會返回您的圖標。 您可以像這樣創建自己的溢出:
<item android:title=""
android:id="@+id/overflow"
android:showAsAction="always"
android:icon="@drawable/overflow_icon">
<menu >
<item android:id="@+id/back"
android:icon="@drawable/back1"
android:title="Back" />
<item android:id="@+id/My_Profile"
android:icon="@drawable/myprofile"
android:title="My Profile" />
<item android:id="@+id/Job_Alert"
android:icon="@drawable/jobalert4"
android:title="Job Alert !" />
<item android:id="@+id/saved_job"
android:icon="@drawable/jobapplied"
android:title="Saved Job"/>
<item android:id="@+id/Logout"
android:icon="@drawable/logout"
android:title="Logout" />
</menu>
</item>
您可以使用此處描述的反射: https ://stackoverflow.com/a/18431605/4521603
或者,如果您使用 Xamarin / C#:
添加:
using Java.Lang.Reflect;
然后在您的代碼中使用它:
PopupMenu puMenu = new PopupMenu(Activity, v)
Field field = puMenu.Class.GetDeclaredField("mPopup");
field.Accessible = true;
Java.Lang.Object menuPopupHelper = field.Get(puMenu);
Method setForceIcons = menuPopupHelper.Class.GetDeclaredMethod("setForceShowIcon", Java.Lang.Boolean.Type);
setForceIcons.Invoke(menuPopupHelper, true);
puMenu.Inflate (Resource.Menu.your_actions);
puMenu.Show ();
用這個:
/**
* Copied from android.support.v7.widget.PopupMenu.
* "mPopup.setForceShowIcon(true);" in the constructor does the trick :)
*
* @author maikvlcek
* @since 5:00 PM - 1/27/14
*/
public class IconizedMenu implements MenuBuilder.Callback, MenuPresenter.Callback {
private Context mContext;
private MenuBuilder mMenu;
private View mAnchor;
private MenuPopupHelper mPopup;
private OnMenuItemClickListener mMenuItemClickListener;
private OnDismissListener mDismissListener;
/**
* Callback interface used to notify the application that the menu has closed.
*/
public interface OnDismissListener {
/**
* Called when the associated menu has been dismissed.
*
* @param menu The PopupMenu that was dismissed.
*/
public void onDismiss(IconizedMenu menu);
}
/**
* Construct a new PopupMenu.
*
* @param context Context for the PopupMenu.
* @param anchor Anchor view for this popup. The popup will appear below the anchor if there
* is room, or above it if there is not.
*/
public IconizedMenu(Context context, View anchor) {
mContext = context;
mMenu = new MenuBuilder(context);
mMenu.setCallback(this);
mAnchor = anchor;
mPopup = new MenuPopupHelper(context, mMenu, anchor);
mPopup.setCallback(this);
mPopup.setForceShowIcon(true);
}
/**
* @return the {@link android.view.Menu} associated with this popup. Populate the returned Menu with
* items before calling {@link #show()}.
*
* @see #show()
* @see #getMenuInflater()
*/
public Menu getMenu() {
return mMenu;
}
/**
* @return a {@link android.view.MenuInflater} that can be used to inflate menu items from XML into the
* menu returned by {@link #getMenu()}.
*
* @see #getMenu()
*/
public MenuInflater getMenuInflater() {
return new SupportMenuInflater(mContext);
}
/**
* Inflate a menu resource into this PopupMenu. This is equivalent to calling
* popupMenu.getMenuInflater().inflate(menuRes, popupMenu.getMenu()).
* @param menuRes Menu resource to inflate
*/
public void inflate(int menuRes) {
getMenuInflater().inflate(menuRes, mMenu);
}
/**
* Show the menu popup anchored to the view specified during construction.
* @see #dismiss()
*/
public void show() {
mPopup.show();
}
/**
* Dismiss the menu popup.
* @see #show()
*/
public void dismiss() {
mPopup.dismiss();
}
/**
* Set a listener that will be notified when the user selects an item from the menu.
*
* @param listener Listener to notify
*/
public void setOnMenuItemClickListener(OnMenuItemClickListener listener) {
mMenuItemClickListener = listener;
}
/**
* Set a listener that will be notified when this menu is dismissed.
*
* @param listener Listener to notify
*/
public void setOnDismissListener(OnDismissListener listener) {
mDismissListener = listener;
}
/**
* @hide
*/
public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
if (mMenuItemClickListener != null) {
return mMenuItemClickListener.onMenuItemClick(item);
}
return false;
}
/**
* @hide
*/
public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
if (mDismissListener != null) {
mDismissListener.onDismiss(this);
}
}
/**
* @hide
*/
public boolean onOpenSubMenu(MenuBuilder subMenu) {
if (subMenu == null) return false;
if (!subMenu.hasVisibleItems()) {
return true;
}
// Current menu will be dismissed by the normal helper, submenu will be shown in its place.
new MenuPopupHelper(mContext, subMenu, mAnchor).show();
return true;
}
/**
* @hide
*/
public void onCloseSubMenu(SubMenuBuilder menu) {
}
/**
* @hide
*/
public void onMenuModeChange(MenuBuilder menu) {
}
/**
* Interface responsible for receiving menu item click events if the items themselves
* do not have individual item click listeners.
*/
public interface OnMenuItemClickListener {
/**
* This method will be invoked when a menu item is clicked if the item itself did
* not already handle the event.
*
* @param item {@link MenuItem} that was clicked
* @return <code>true</code> if the event was handled, <code>false</code> otherwise.
*/
public boolean onMenuItemClick(MenuItem item);
}
}
來源: https ://gist.github.com/mediavrog/9345938
如果在任何活動中嘗試此代碼,則將 getbBaseContext() 替換為此活動上下文
PopupMenu popup = new PopupMenu(this, v);
在 popupMenu.show() 之前; 利用
try {
Field mFieldPopup=popupMenu.getClass().getDeclaredField("mPopup");
mFieldPopup.setAccessible(true);
MenuPopupHelper mPopup = (MenuPopupHelper) mFieldPopup.get(popupMenu);
mPopup.setForceShowIcon(true);
} catch (Exception e) {
}
如果您不熟悉反射,您可以使用反射來實現這一點在我們的例子中,我們需要在運行時修改 popupMenu 行為,而不是擴展核心類並修改它;)希望有所幫助 嘗試我的方法就像一個魅力
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();
}
setForceShowIcon
函數現在是公開的,不再受到限制,所以它有效!
private fun showPopupMenu(view: View) {
PopupMenu(this, view).apply {
menuInflater.inflate(R.menu.my_menu, menu)
setForceShowIcon(true)
}.show()
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.