簡體   English   中英

Android 上帶有圖標的彈出菜單

[英]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();

但它不顯示圖標。

如何在彈出菜單上設置圖標?

您可以使用MenuBuilderMenuPopupHelper創建帶有圖標的彈出菜單。

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

實際上, 上下文菜單不支持圖標。

如果你想要帶有圖標的上下文菜單/彈出菜單就是方法。

您可以使用QuickAction3D ,它可以提供您想要的功能。

查看可能對您有所幫助的主題

這是因為當您使用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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM