Home » Android » android – How to prevent popup menu from closing on checkbox click

android – How to prevent popup menu from closing on checkbox click

Posted by: admin May 14, 2020 Leave a comment

Questions:

I search a lot on net but there is nothing about preventing popup menu from closing.

Whenever i click on checkbox item or any other popup menu item, popup menu dismiss itself. How can i prevent it from dismissing when user check/uncheck checkbox in popup menu.

I’m showing popup menu on actionbar-menu item’s click event.

//main_menu.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.worldofjobs.woj.MainActivity" >

<item
    android:id="@+id/action_popUpMenu"
    android:icon="@drawable/ic_action_overflow"
    android:title="@string/main_action_popUpMenu"
    app:showAsAction="always"/>

</menu>

//popup_items.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >

<item
    android:id="@+id/refresh_item"
    android:title="@string/main_refresh"/>
<item
    android:id="@+id/checkbox_item"
    android:checkable="true"
    android:title="Start notification"/>
<item
    android:id="@+id/changePasswrod_item"
    android:title="@string/main_changePassword"/>
<item
    android:id="@+id/deleteAccount_item"
    android:title="@string/main_deleteAccount"/>
<item
    android:id="@+id/logout_item"
    android:title="@string/main_logout"/>

</menu>

/**
 * Shows popup menu on click of action bar-menu inflates from
 * menu.pop_items-xml
 */
private void showPopup() {

    try {

        View v = findViewById(R.id.action_popUpMenu);

        PopupMenu popup = new PopupMenu(this, v);
        popup.setOnMenuItemClickListener(MainActivity.this);

        MenuInflater inflater = popup.getMenuInflater();
        inflater.inflate(R.menu.pop_items, popup.getMenu());
        popup.show();

    } catch (Exception e) {

        Log.e("MainActivity-showPopup:", e.toString());
    }
}

/**
 * Handles click events of popup menu items
 */
@Override
public boolean onMenuItemClick(MenuItem item) {

    super.onMenuItemSelected(1, item);
    switch (item.getItemId()) {

    case R.id.refresh_item:
        refresh();
        return true;

    case R.id.checkbox_item:
        return true;

    case R.id.changePasswrod_item:
        changePasswordPopup();
        return true;

    case R.id.deleteAccount_item:
        deleteAccount();
        return true;

    case R.id.logout_item:
        session.logout();
        finish();
        return true;
    }
    return true;
}
How to&Answers:

Using popupMenu.show() to immediately re-show the popup menu does not work correctly with checkable menu items when changing their checked states.

Here a method that prevents closing the popup menu in the first place. Make sure that onMenuItemClick returns false.

popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
    @Override
    public boolean onMenuItemClick(MenuItem item) {

        item.setChecked(!item.isChecked());

        // Do other stuff

        // Keep the popup menu open
        item.setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
        item.setActionView(new View(context));
        item.setOnActionExpandListener(new MenuItem.OnActionExpandListener() {
            @Override
            public boolean onMenuItemActionExpand(MenuItem item) {
                return false;
            }

            @Override
            public boolean onMenuItemActionCollapse(MenuItem item) {
                return false;
            }
        });
        return false;
    }
});

Answer:

The trick here is to show the menu right after it dismisses.
Below is a sample code snippet:

popupMenu.setOnMenuItemClickListener(new OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
    if(item.getItemId()==R.id.search_by_date_checkbox){
        item.setChecked(!item.isChecked());
    }
    //This is the trick here!!!!
    popupMenu.show();
    return true;
    }

});

You can try this trick with your code! This is how I did it. 🙂

Answer:

Oliver’s answer above (https://stackoverflow.com/a/31727213/2423194) gave me a crash, and its message told me to use MenuItemCompat instead. After some tweaking to this code, it works:

// Keep the popup menu open              
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
item.setActionView(new View(getContext()));
MenuItemCompat.setOnActionExpandListener(item, new MenuItemCompat.OnActionExpandListener() {
    @Override
    public boolean onMenuItemActionExpand(MenuItem item) {
        return false;
    }

    @Override
    public boolean onMenuItemActionCollapse(MenuItem item) {
        return false;
    }
});

Thanks Oliver!

Answer:

In your case R.id.checkbox_item

return false;

This will tell the system that the event has not yet been handeled and it will not dimiss the menu. See HERE

Answer:

Try declaring the PopupMenu globally and calling popup.show(); before returning true in onMenuItemClick function.

Answer:

Got it working by adding popup.show(); on the click of the button and at the end of the click.

final ImageButton layerButton = (ImageButton) findViewById(R.id.layers);
final PopupMenu popup = new PopupMenu(MapsActivity.this, layerButton);
popup.getMenuInflater().inflate(R.menu.toolbar_menu, popup.getMenu());

layerButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            //Here
            popup.show();

            popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
                @Override
                public boolean onMenuItemClick(MenuItem item) {

                    handleClicksOnCheckBoxes(item);

                    return true;

                }

            });

            //And here
            popup.show();


        }
    });

However, this is not an optimal solution because if the list has so many items that it will be possible to scroll the list, the list will be scrolled to the top when clicking on an item.