Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AppCompat PopUp menu RuntimeException

I am using following class to create iconized popup menu:

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

}

However if I try to run it on lolipop it causes error. It works fine on devices with API level < 21. Here is the logcat:

02-15 06:08:09.165: E/AndroidRuntime(3824): FATAL EXCEPTION: main
02-15 06:08:09.165: E/AndroidRuntime(3824): Process: hzs.sk.hzs, PID: 3824
02-15 06:08:09.165: E/AndroidRuntime(3824): java.lang.IllegalStateException: Could not execute method of the activity
02-15 06:08:09.165: E/AndroidRuntime(3824):     at android.view.View$1.onClick(View.java:4007)
02-15 06:08:09.165: E/AndroidRuntime(3824):     at android.view.View.performClick(View.java:4756)
02-15 06:08:09.165: E/AndroidRuntime(3824):     at android.view.View$PerformClick.run(View.java:19749)
02-15 06:08:09.165: E/AndroidRuntime(3824):     at android.os.Handler.handleCallback(Handler.java:739)
02-15 06:08:09.165: E/AndroidRuntime(3824):     at android.os.Handler.dispatchMessage(Handler.java:95)
02-15 06:08:09.165: E/AndroidRuntime(3824):     at android.os.Looper.loop(Looper.java:135)
02-15 06:08:09.165: E/AndroidRuntime(3824):     at android.app.ActivityThread.main(ActivityThread.java:5221)
02-15 06:08:09.165: E/AndroidRuntime(3824):     at java.lang.reflect.Method.invoke(Native Method)
02-15 06:08:09.165: E/AndroidRuntime(3824):     at java.lang.reflect.Method.invoke(Method.java:372)
02-15 06:08:09.165: E/AndroidRuntime(3824):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
02-15 06:08:09.165: E/AndroidRuntime(3824):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
02-15 06:08:09.165: E/AndroidRuntime(3824): Caused by: java.lang.reflect.InvocationTargetException
02-15 06:08:09.165: E/AndroidRuntime(3824):     at java.lang.reflect.Method.invoke(Native Method)
02-15 06:08:09.165: E/AndroidRuntime(3824):     at java.lang.reflect.Method.invoke(Method.java:372)
02-15 06:08:09.165: E/AndroidRuntime(3824):     at android.view.View$1.onClick(View.java:4002)
02-15 06:08:09.165: E/AndroidRuntime(3824):     ... 10 more
02-15 06:08:09.165: E/AndroidRuntime(3824): Caused by: java.lang.RuntimeException: Failed to resolve attribute at index 6
02-15 06:08:09.165: E/AndroidRuntime(3824):     at android.content.res.TypedArray.getLayoutDimension(TypedArray.java:603)
02-15 06:08:09.165: E/AndroidRuntime(3824):     at android.view.ViewGroup$LayoutParams.setBaseAttributes(ViewGroup.java:6423)
02-15 06:08:09.165: E/AndroidRuntime(3824):     at android.view.ViewGroup$MarginLayoutParams.<init>(ViewGroup.java:6591)
02-15 06:08:09.165: E/AndroidRuntime(3824):     at android.widget.FrameLayout$LayoutParams.<init>(FrameLayout.java:735)
02-15 06:08:09.165: E/AndroidRuntime(3824):     at android.widget.FrameLayout.generateLayoutParams(FrameLayout.java:679)
02-15 06:08:09.165: E/AndroidRuntime(3824):     at android.widget.FrameLayout.generateLayoutParams(FrameLayout.java:62)
02-15 06:08:09.165: E/AndroidRuntime(3824):     at android.view.LayoutInflater.inflate(LayoutInflater.java:492)
02-15 06:08:09.165: E/AndroidRuntime(3824):     at android.view.LayoutInflater.inflate(LayoutInflater.java:414)
02-15 06:08:09.165: E/AndroidRuntime(3824):     at android.support.v7.internal.view.menu.MenuPopupHelper$MenuAdapter.getView(MenuPopupHelper.java:370)
02-15 06:08:09.165: E/AndroidRuntime(3824):     at android.support.v7.internal.view.menu.MenuPopupHelper.measureContentWidth(MenuPopupHelper.java:219)
02-15 06:08:09.165: E/AndroidRuntime(3824):     at android.support.v7.internal.view.menu.MenuPopupHelper.tryShow(MenuPopupHelper.java:153)
02-15 06:08:09.165: E/AndroidRuntime(3824):     at android.support.v7.internal.view.menu.MenuPopupHelper.show(MenuPopupHelper.java:125)
02-15 06:08:09.165: E/AndroidRuntime(3824):     at hzs.sk.hzs.IconizedMenu.show(IconizedMenu.java:88)
02-15 06:08:09.165: E/AndroidRuntime(3824):     at hzs.sk.hzs.MainActivity.showMenu(MainActivity.java:294)
02-15 06:08:09.165: E/AndroidRuntime(3824):     ... 13 more

activity which uses this extends Activity, not ActionBarActivity. Any ideas why is it generating an error?

Thanks in forward

EDIT: I have tried using default appCompat PopUp menu (so its without icons) and it is throwing same error. Any ideas?

like image 980
horin Avatar asked Feb 15 '15 06:02

horin


2 Answers

If you are using Appcompat and lollipop try adding new style

<style name="MyPopupMenu" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="android:popupBackground">#0F213F</item>
    <item name="android:disabledAlpha">0.5</item>
</style>

and create the popup menu

Context wrapper = new ContextThemeWrapper(context, R.style.MyPopupMenu);
            PopupMenu popup = new PopupMenu(wrapper, view);
like image 174
Amir Dadgari Avatar answered Nov 04 '22 11:11

Amir Dadgari


In this case MenuPopupHelper.MenuAdapter#getView() try to inflate ITEM_LAYOUT = R.layout.abc_popup_menu_item_layout and during this process android.support.v7.internal.view.menu.ListMenuItemView created and require R.styleable.MenuView (look inside to find - declare-styleable name="MenuView") where attribute at index 6 is attr name="android:itemIconDisabledAlpha" this mean that no this attribute defined in application theme. Required attribute defined in <style name="Theme"> for any platform as <item name="disabledAlpha">0.5</item> this is link.

To use default value just extend application theme by one of the themes that extends <style name="Theme">.

I recommend following solution:

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
</style>

or any other Theme.AppCompat with NoActionBar if you want to use Toolbar for older than v21 platforms with all new features available as replacement of ActionBar component.

But actually feel free to use other themes like Holo or Material if it's really required.

Good luck!

And feel free to ask.

like image 25
Nikolay Nikiforchuk Avatar answered Nov 04 '22 10:11

Nikolay Nikiforchuk