I have options menu item in my application. Requirement was to add a toggle button to a menu item. Is this possible?
In Android, ToggleButton is used to display checked and unchecked state of a button. ToggleButton basically an off/on button with a light indicator which indicate the current state of toggle button. The most simple example of ToggleButton is doing on/off in sound, Bluetooth, wifi, hotspot etc.
In Android, Switch is a two-state toggle switch widget that can select between two options. It is used to display checked and unchecked state of a button providing slider control to user. Switch is a subclass of CompoundButton.
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.
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:
onOptionsItemSelected()
doesn't actually get called when I toggle the switch.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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With