Search code examples
androidxamarin.androidandroid-optionsmenu

Prevent options menu from closing on OptionItemSelected


I got an options menu with a bunch of checkboxes in it. I'd like to check a bunch of them on or off, but the menu closes automaticly every time I check just one. Can I prevent the menu from closing when an item has been selected? I'd also want to control when the closing happens and when it's prevented.

Activity.cs (excluding everything not related to options menu)

public class Activity: ReactiveActivity<ViewModel>, IAppCompatCallback
{

    public override bool OnCreateOptionsMenu(IMenu menu)
    {
        var inflater = MenuInflater;
        inflater.Inflate(Resource.Menu.actions, menu);
        return true;
    }

    public override bool OnOptionsItemSelected(IMenuItem item)
    {
        if(item.ItemId == Resource.Id.action_settings) {
           StartActivity(typeof(SettingsActivity));
        }
        else {
           //Code changing the view based on selections
        }
        return base.OnOptionsItemSelected(item);
    }
}

actions.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:title="Choose options...">
  <menu>
    <group android:checkableBehavior="all">
      <item android:id="@+id/checkOption1"
            android:title="Option 1" 
            android:checked="true" />
      <item android:id="@+id/checkOption2"
            android:title="Option 2"
            android:checked="true" />
      <item android:id="@+id/checkOption3"
            android:title="Option 3"
            android:checked="true" />
      <item android:id="@+id/checkOption4"
            android:title="Option 4"
            android:checked="true" />
      <item android:id="@+id/checkOption5"
            android:title="Option 5"
            android:checked="true" />
      <item android:id="@+id/checkOption6"
            android:title="Option 6"
            android:checked="true" />
      <item android:id="@+id/checkOption7"
            android:title="Option 7"
            android:checked="true" />
    </group>
  </menu>
  </item>
  <item android:id="@+id/action_settings"
        android:title="@string/action_settings"
        android:showAsAction="never"/>
</menu>

Solution

  • I got an options menu with a bunch of checkboxes in it. I'd like to check a bunch of them on or off, but the menu closes automaticly every time I check just one. Can I prevent the menu from closing when an item has been selected? I'd also want to control when the closing happens and when it's prevented.

    For Menus, I didn't find a proper way to control the closing behavior.

    But for your requirement, Dialog is a much better choice:

    1. remove the sub menu in your action.xml and add an id for Choose Options... Item:

      <?xml version="1.0" encoding="utf-8"?>
      <menu xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:title="Choose options..." android:id="@+id/chooseOption"></item>
        <item android:id="@+id/action_settings"
              android:title="Settings"
              android:showAsAction="never"/>
      </menu>
      
    2. Create your DialogFragment together with AlertDialog:

      public class MyDialogFragment:DialogFragment
      {
          string[] Items { get; set; }
          bool[] CheckedItems { get; set; }
      
          public MyDialogFragment(string[] items,bool[] checkedItems)
          {
              Items = items;
              checkedItems = checkedItems;
          }
          public override Dialog OnCreateDialog(Bundle savedInstanceState)
          {
              AlertDialog.Builder builder = new AlertDialog.Builder(this.Activity);
              builder.SetMultiChoiceItems(Items, CheckedItems, new DialogItemClickhandler());
              // Create the AlertDialog object and return it
              return builder.Create();
          } 
      }
      
      public class DialogItemClickhandler : Java.Lang.Object, IDialogInterfaceOnMultiChoiceClickListener
      {
          public void OnClick(IDialogInterface dialog, int which, bool isChecked)
          {
             //Item Click Implementation
          }
      }
      
    3. Open the dialog when user clicks the Choose Options... Menu Item:

      public class MainActivity : Activity
      {
          protected override void OnCreate(Bundle bundle)
          {
              base.OnCreate(bundle);
              SetContentView (Resource.Layout.Main);
          }
      
      
          public override bool OnCreateOptionsMenu(IMenu menu)
          {
              MenuInflater.Inflate(Resource.Menu.Actions, menu);
              return true;
          }
      
          public override bool OnMenuItemSelected(int featureId, IMenuItem item)
          {
              switch (item.ItemId)
              {
                  case Resource.Id.chooseOption:
                      OpenDialogFragment();//Open the dialog
                      break;
                  default:break;
              }
              return true;
          }
      
          private void OpenDialogFragment()
          {
      
              //init the Dialog items
              string[] items = new string[] {
                  "Options 1",
                  "Options 2",
                  "Options 3",
                  "Options 4",
                  "Options 5",
                  "Options 6"
              };
      
              bool[] checkedItems = new bool[] {
                  true,
                  false,
                  true,
                  false,
                  true,
                  false
              };
              MyDialogFragment dialog = new MyDialogFragment(items,checkedItems);
              dialog.Show(FragmentManager, "tag");
          }
      }