33

I have options menu item in my application. Requirement was to add a toggle button to a menu item. Is this possible?

Anju
  • 9,379
  • 14
  • 55
  • 94

5 Answers5

63

As of this writing there are 3 options.

1) Use app:actionViewClass. Example:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:title="Switch!"
        app:actionViewClass="android.widget.Switch"
        app:showAsAction="always" />
</menu>

2) You can use a custom layout in a menu item to add toggle button. Example:

Create a layout with Switch (alternatively, you may also use ToggleButton), res/layout/menu_switch.xml:

<?xml version="1.0" encoding="utf-8"?>
<Switch xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:padding="64dp" />

And use that layout in menu item:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:title="@string/switch_button_title"
        app:actionLayout="@layout/menu_switch"
        app:showAsAction="always" />
</menu>

3) You need to set android:checkable property of the menu to true and control its checked state in runtime. Example:

Menu:

<item
    android:id="@+id/checkable_menu"
    android:checkable="true"
    android:title="@string/checkable" />

Activity:

private boolean isChecked = false;

@Override
public boolean onPrepareOptionsMenu(Menu menu) {
    MenuItem checkable = menu.findItem(R.id.checkable_menu);
    checkable.setChecked(isChecked);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.checkable_menu:
            isChecked = !item.isChecked();
            item.setChecked(isChecked);
            return true;
        default:
            return false;
    }
}

Hope this helps.

ozbek
  • 20,955
  • 5
  • 61
  • 84
  • 3
    This provides a checkbox only. – Anju Feb 03 '14 at 10:48
  • 4
    A checkbox is essentially a toggle button: it toggles between two states :) – ozbek Feb 03 '14 at 11:53
  • I could not see any checkbox :\ – Li3ro May 12 '15 at 09:01
  • @Li3ro, please make sure that you have followed the steps correctly. This solution is working all the way to API level 22. – ozbek May 12 '15 at 09:09
  • Well, According to http://developer.android.com/guide/topics/ui/menus.html : Note: Menu items in the Icon Menu (from the options menu) cannot display a checkbox or radio button. If you choose to make items in the Icon Menu checkable, you must manually indicate the checked state by swapping the icon and/or text each time the state changes. --- And this is exactly my case – Li3ro May 12 '15 at 10:57
  • See [this screenshot](https://lh4.ggpht.com/c0Cz5tQ7FpMfmjkBYJLWz7Ga9kXBd-wPS5gjCJZ3xjeDtRGEEFpFZGMqPxGpgNk3ANV0=h900): if the checkbox in the right top menu is not what you are talking about, then perhaps you should start a separate question. – ozbek May 12 '15 at 11:54
  • 1
    https://stackoverflow.com/questions/31400870/add-toggle-button-to-the-menu-to-stop-and-start-service/34760443#34760443 – Faizan Mubasher Nov 22 '17 at 07:07
  • I don't see a checkbox – Someone Somewhere Apr 22 '19 at 23:43
  • @SomeoneSomewhere: if you don't see the checkbox, perhaps, your problem is something else. So, please post a separate question. – ozbek Apr 23 '19 at 02:51
  • I am trying to use the menu as a navigation-drawer menu. Maybe that menu has different rules? – Someone Somewhere Apr 23 '19 at 10:37
  • @SomeoneSomewhere, works on my end with navigation drawer as well. – ozbek Apr 25 '19 at 08:49
  • I read that the style can cause problems with it. I am using ` – Someone Somewhere Apr 26 '19 at 12:30
6

I had a couple of issues when using a actionViewClass="android.widget.Switch in a menu item. It does actually show a switch on the ToolBar, although for me:

  • The onOptionsItemSelected() doesn't actually get called when I toggle the switch.
  • Using setChecked() on the MenuItem doesn't toggle its state.

Upon debugging and removing the actionViewClass="android.widget.Switch, the onOptionsItemSelected() gets called again.

Not sure what was going on; Maybe that I am using a custom ActionBar that I set using setSupportActionBar(), and using OptionsMenu callbacks within a fragment by enabling it with setHasOptionsMenu(true).

I get this solved by inflating the switch itself, and set OnCheckedChangeListener on it

<item
    android:id="@+id/my_switch"
    android:title=""
    app:actionViewClass="androidx.appcompat.widget.SwitchCompat"
    app:showAsAction="always" />

And in Fragment

@Override
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
    inflater.inflate(R.menu.my_menu, menu);
    MenuItem menuItem = menu.findItem(R.id.my_switch);
    SwitchCompat mySwitch = (SwitchCompat) menuItem.getActionView();

    mySwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
        // Do something when `isChecked` is true or false
    });

}

And to toggle the switch programmatically, call setChecked() on the Switch, not on the MenuItem.

Zain
  • 37,492
  • 7
  • 60
  • 84
2

use app:actionViewClass

 <item android:id="@+id/id"
    android:title="@string/string"
    app:actionViewClass="android.widget.ToggleButton"
    android:orderInCategory="80"
    app:showAsAction="always" />
GreatC
  • 342
  • 4
  • 9
0
public boolean onPrepareOptionsMenu(final Menu menu) {       
      if(super.mMapView.isTraffic()) 
           menu.findItem(MENU_TRAFFIC_ID).setIcon(R.drawable.traffic_off_48); 
      else 
           menu.findItem(MENU_TRAFFIC_ID).setIcon(R.drawable.traffic_on_48); 

      return super.onPrepareOptionsMenu(menu); 
 }
Digvesh Patel
  • 6,503
  • 1
  • 20
  • 34
  • Icon I already have for menu items…I mean along with icon, title can I have a toggle button also? I need to save the toggle status.. – Anju Jan 22 '14 at 12:05
0

Do you mean you want to add a toggle button as one of the elements/items appearing in the options menu or add a button to a list item from the menu?

Then you can do it with a custom layout(use a ListView within if you want) and inflating it in the

public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.main_menu, menu);
    return true;
}

and you can save the values each time the button is toggles.

public boolean onOptionsItemSelected(MenuItem item) {
  switch (item.getItemId()) {
    case R.id.btnToggleValue:
      // save it here
      return true;
    case R.id.btnSecond:
      ...
      return true;
    default:
      return super.onOptionsItemSelected(item);
  }
}
ozbek
  • 20,955
  • 5
  • 61
  • 84
Pararth
  • 8,114
  • 4
  • 34
  • 51