Switch in Navigation drawer item with Design Support Library on Android

14,478

Solution 1

Your menu item for the navigation drawer:

<item
    android:id="@+id/nav_item1"
    android:icon="@drawable/ic_item1"
    android:title="item1"
    app:actionLayout="@layout/layout_switch"
    />

and the layout for that item:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.SwitchCompat
        android:id="@+id/drawer_switch"
        android:layout_width="fill_parent"
        android:layout_height="match_parent"
        android:text=""/>

</LinearLayout>

EDIT:

I ended up using a different approach. In fact, I found out that you can use any view in the drawer, so there's no point in bothering with the menu stuff. Just create a view the usual way (with listeners, etc.) and add in to the drawer.

Solution 2

One way I have found of doing this would be to use setActionView on the menuItem you want:

mNavigationView.getMenu().findItem(R.id.nav_connect)
        .setActionView(new Switch(this));

// To set whether switch is on/off use:
((Switch) mNavigationView.getMenu().findItem(R.id.nav_connect).getActionView()).setChecked(true);

Probably want a click listener as well to change the state of the Switch:

mNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
    @Override
    public boolean onNavigationItemSelected(MenuItem menuItem) {

        switch (menuItem.getItemId()) {
            case R.id.nav_connect:
                ((Switch) menuItem.getActionView()).toggle();
                return true;
        }
    }
}

I haven't tried, but you could probably use android:actionLayout="@layout/switch_layout" in xml and point to a custom layout you created.

Also could try using an ActionProvider which might offer a little more robustness. I haven't tried this method either though.

Solution 3

None of the answers seems to be complete so after some more research here is what I came up with:

drawer_switch.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.SwitchCompat 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/drawer_switch"
    android:layout_width="fill_parent"
    android:layout_height="match_parent" />

drawer_menu.xml:

<?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/header">
        <menu>
            <item
                android:id="@+id/switch_item"
                android:icon="@drawable/ic_switch_item"
                app:actionLayout="@layout/drawer_switch"
                android:title="@string/switch_item" />
        </menu>
    </item>
</menu>

DrawerActivity.java:

SwitchCompat drawerSwitch = (SwitchCompat) navigationView.getMenu().findItem(R.id.switch_item).getActionView();
drawerSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (isChecked) {
                    // do stuff
                } else {
                    // do other stuff
                }
            }
});

DrawerActivity.java:

@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {

    int id = item.getItemId();

    if (id == R.id.switch_item) {
        return false;
    }

    closeDrawer();
    return true;
}

Solution 4

I did something like this.

navigationView.getMenu().findItem(R.id.vibrate)
            .setActionView(new Switch(this));

    Switch vibrateSwitch =(Switch) 
navigationView.getMenu().findItem(R.id.vibrate).getActionView();
    vibrateSwitch.setChecked(true);
    vibrateSwitch.setOnCheckedChangeListener(new 
CompoundButton.OnCheckedChangeListener(){
        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean 
isChecked){
                SharedPreferences sharedPreferences = 
getSharedPreferences(getString(R.string.MyPREFERENCES), MODE_PRIVATE);
                SharedPreferences.Editor editor = sharedPreferences.edit();
                editor.putBoolean(getString(R.string.VIBRATE), isChecked);
                editor.commit();
        }

    });

Solution 5

For those of you using Kotlin Extensions

  1. Menu file
<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">

    <item
        android:id="@+id/nav_notifications_switch"
        android:icon="@drawable/ic_notifications"
        android:title="@string/notifications"
        app:actionLayout="@layout/drawer_notifications_switch" />

</menu>
  1. Switch layout file
<Switch xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/toggleSwitch"
    android:layout_width="fill_parent"
    android:layout_height="match_parent" />
  1. Access in code
nav_view.menu.findItem(R.id.nav_notifications_switch)
    .actionView
    .toggleSwitch
    .setOnCheckedChangeListener { _, isChecked ->
        
    }
Share:
14,478
Marcin Lagowski
Author by

Marcin Lagowski

Java Developer. Interests: new technologies, functional programming, devops, docker, automation, continuous integration, android, kotlin.

Updated on June 14, 2022

Comments

  • Marcin Lagowski
    Marcin Lagowski almost 2 years

    I need to put Switch inside item in navigation drawer. I'm using new design support library, but I cannot find if it is posibble at all. When using

    android:checkable
    

    item is just full selected and that is not what I wish.

    This is screenshot of what I really want. Is that possible to achieve that?

    enter image description here

  • Marcin Lagowski
    Marcin Lagowski almost 9 years
    Do you mean to put <Switch> between <NavigationView> tags? I can do that but all I got is text view and switch drawn on navigation drawer ImageView not as part of it but on it.
  • Marcin Lagowski
    Marcin Lagowski over 7 years
    There is no Switch in your solution.
  • Marcin Lagowski
    Marcin Lagowski over 7 years
    Thank you very much. It works. I regret that I did not know that a year ago.
  • mehmet
    mehmet about 7 years
    How to add listener for switch, can you add codes to your respond plesae
  • codemoonger
    codemoonger almost 7 years
    How do you add a listener to the switch since you apparently can't do it the normal way.
  • lenooh
    lenooh about 6 years
    mehmet & mogren3000: I ended up using a different approach. In fact, I found out that you can use any view in the drawer, so there's no point in bothering with the menu stuff. Just create a view the usual way (with listeners, etc.) and add in to the drawer.
  • gautam
    gautam about 6 years
    How to know if switch has toggled in java file ?
  • roghayeh hosseini
    roghayeh hosseini over 5 years
    @lenooh if i use this in my menu, how listen for switch?
  • lenooh
    lenooh over 5 years
    roghayeh hosseini: As I wrote in my comment " I ended up using a different approach. In fact, I found out that you can use any view in the drawer, so there's no point in bothering with the menu stuff. Just create a view the usual way (with listeners, etc.) and add in to the drawer."
  • EdgeDev
    EdgeDev over 4 years
    your code does not work. I kept getting Error inflating class com.google.android.material.navigation.NavigationView
  • lenooh
    lenooh over 4 years
    EdgeDev: there's something wrong with your code. Check your NavigationView stuff. Anyway, I don't recommend this approach, see my comment.
  • Pradeesh tet
    Pradeesh tet about 4 years
    If you get NULLPointer try this - switch is referenced inside nav item. (Switch) navigationView.getMenu().findItem(R.id.item).getActionView()‌​.findViewById(R.id.s‌​witch);
  • Abraham Mathew
    Abraham Mathew almost 4 years
    Disclaimer:Please confirm that you are using app:actionLayout="@layout/layout_menu_profile" and not android:actionLayout="@layout/layout_menu_profile"
  • Abraham Mathew
    Abraham Mathew almost 4 years
    Disclaimer:Please confirm that you are using app:actionLayout="@layout/layout_menu_profile" and not android:actionLayout="@layout/layout_menu_profile"
  • Sir Codesalot
    Sir Codesalot almost 4 years
    @AbrahamMathew yes I am. You can see it in the answer itself.