58

I've been experimenting with simplifying some navigation drawer code by making use of the new NavigationView class in the Android design support library. It works great if you just want icons on the left, and text on the right like in the example in the documentation, but what if I want to add a single custom view to the layout which has an android.support.v7.widget.SwitchCompat like in the Google Play Movies app (see screenshot below)?

Google Play Movies

I've tried using the actionLayout attribute to specify a custom layout file like in the example code below, however that attribute appeared to be ignored as it didn't work.

res/menu/navigation_drawer.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <group android:id="@+id/group1"
            android:checkableBehavior="single">
        <item
            android:id="@+id/nav_screen1"
            android:icon="@drawable/ic_list_black_24dp"
            android:title="Screen 1" />
        <item
            android:id="@+id/nav_screen2"
            android:icon="@drawable/ic_search_black_24dp"
            android:title="Screen2"/>
    </group>
    <group  android:id="@+id/group2">
        <item
            android:id="@+id/nav_custom"
            android:icon="@drawable/custom_icon_24dp"
            app:actionLayout="@layout/nav_drawer_switch"
            android:title="Custom item with switch"/>
        <item
            android:id="@+id/nav_settings"
            android:icon="@drawable/ic_settings_black_24dp"
            android:title="Settings"/>
    </group>
</menu>

res/layout/nav_drawer_switch.xml

<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:layout_width="fill_parent"
        android:layout_height="match_parent"
        android:text="Custom item with switch"/>
</LinearLayout>

How can I get this to work? Ideally I'd like to add the custom view while still making use of my Menu layout, but if that's not possible without using a crude hack (like tapping into an existing layout generated by the support library) then I'd like to know the solution with the least amount of code, and which still makes it worth transitioning to NavigationView.

Tim Rae
  • 3,167
  • 2
  • 28
  • 35
  • 3
    You can't customize item with the current NavigationView implementation. NavigationView use a ListView to polulate item which is a TextView and currently there are no way to customize that ListView item. – Wayne Jul 02 '15 at 15:51
  • 1
    Is there a way to add 2 lines of text in menu item? I tried adding through actionLayout and it by adds to the right side instead of below. Example like Google drive-> Upgrade storage option shows 2 line of text – Siju Jun 11 '16 at 09:14

5 Answers5

43

The actionLayout attribute is now supported in Android Support Library 23.1:

NavigationView provides a convenient way to build a navigation drawer, including the ability to creating menu items using a menu XML file. We’ve expanded the functionality possible with the ability to set custom views for items via app:actionLayout or using MenuItemCompat.setActionView().

So the code in the question should just work now.

Tim Rae
  • 3,167
  • 2
  • 28
  • 35
20

NavigationView is a subclass of FrameLayout, which can have multiple children:

You can, however, add multiple children to a FrameLayout and control their position within the FrameLayout by assigning gravity to each child, using the android:layout_gravity attribute.

That means you can add a custom view to your NavigationView:

<android.support.design.widget.NavigationView
    android:layout_height="match_parent"
    android:layout_width="wrap_content"
    android:layout_gravity="start"
    android:fitsSystemWindows="true"
    app:menu="@menu/side_menu">

    <LinearLayout 
        android:orientation="horizontal" 
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:layout_gravity="bottom">

        <android.support.v7.widget.SwitchCompat
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text="night_mode"/>
    </LinearLayout>
</android.support.design.widget.NavigationView>
Vera Rivotti
  • 500
  • 4
  • 9
  • Thanks for your answer! Unfortunately I can't find a way to set the position of the `LinearLayout` exactly beneath the existing (library generated child layout). I presume you meant I could use `layout_gravity="bottom"` and empirically adjust the height until it looks ok, but this is not great. – Tim Rae Jun 13 '15 at 06:10
  • 1
    this solution is like no use at all NavigationView and use just DrawerLayout, i'm wrong? – Zorb Jul 05 '15 at 22:34
  • This solution is a way to add a custom view to the bottom of the NavigationView. The NavigationView is still used to the menu layout. – Vera Rivotti Jul 06 '15 at 11:09
  • 4
    NavigationView is a FrameLayout which contains a ListView internally. This workaround does not allow to add custom menu items to the ListView, only to display something on top of it which is not in sync with the ListView's scroll. – BladeCoder Jul 27 '15 at 21:17
  • Yes, you are right, this solution adds a static footer. By the way, this may help others with similar problems: http://stackoverflow.com/questions/30543605/how-to-add-footer-to-navigationview-android-support-design-library – Vera Rivotti Jul 28 '15 at 18:01
  • how do you get onclick of that? – Dhinakaran Thennarasu Oct 04 '15 at 09:33
  • thanks you are safe my time. used direct id of viewfindViewById(R.id.nav_item_temp_tv).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Utility.showToast(MainActivity.this,"clikedddd"); } }); – Uday Nayak Jun 16 '16 at 11:13
  • In my case this is a useful approach, but the problem is that if the NavigationView menu has lots of items, some of them may get hidden by the "footer". A somewhat hacky workaround is to add empty, dummy items at the end of the menu (``) taking up vertical space, so that the real menu content can be scrolled into view. – Jonik Oct 20 '16 at 15:03
10

I had the same problem and found that NavigationView behaves differently depending on:

  • Whether you set the android:title and android:icon attributes on item or not
  • What kind of view your action layout contains (e.g. TextView or others)

Not setting the attributes worked for completely customizing the 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"
    xmlns:tools="http://schemas.android.com/tools"
    tools:showIn="navigation_view">

    <item
        android:id="@+id/nav_custom"
        android:title="@null"
        app:actionLayout="@layout/nav_drawer_switch" />
</menu>

(Note that you can also just not set android:title, but that results in a warning in Android Studio.)

The result:

navigation view with switch as custom action layout

(This is with version 27.1.1 of com.android.support:design, not sure about other versions.)

robinst
  • 30,027
  • 10
  • 102
  • 108
  • 1
    This should be the accepted answer! Thanks for this! – VIN Feb 11 '21 at 06:06
  • This answer guided me to add extra layout elements to my menu's `item`s. In my case, adding a extra icon to the right side. Now I wonder: how can I control each item's `actionLayout` (and their children of course) attributes programatically, in my case, either to change extra icon's image or switch if it's either visible or invisible? Maybe I end up making a new question from this eventually... EDIT: Said and done, [here is my question](https://stackoverflow.com/q/73683267/3692177) – SebasSBM Sep 11 '22 at 23:33
6

create a layout with switchcompat and mention it in menu item as

<item android:id="@+id/notification"
        android:title="Notification"
        app:actionLayout="@layout/notify" />`

then notify layout add this

<android.support.v7.widget.SwitchCompat
    android:id="@+id/switch_compat"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="10dp"
    android:checked="false"
    android:onClick="notify"/>

onclick is the keyPoint,implement handler in your Activity,then it will work.

Ramesh Bhupathi
  • 408
  • 7
  • 10
0

You might want to take a look at this library: https://github.com/mikepenz/MaterialDrawer. It makes it easy to use Navigation Drawer and it supports custom views.

Loša
  • 2,621
  • 2
  • 14
  • 19
  • Cool, it's not in the documentation but it seems you can easily add any of these provided views, which includes a switch :) https://github.com/mikepenz/MaterialDrawer/tree/develop/library/src/main/java/com/mikepenz/materialdrawer/model I wonder if there any forks for supporting down to SDK 8 though? :-/ – Tim Rae Sep 03 '15 at 02:36