如何在具有菜单布局的NavigationView中添加自定义项?

59
我一直在尝试简化一些导航抽屉代码,通过使用Android设计支持库中的新NavigationView类进行实现。如果您只想在左侧显示图标,在右侧显示文本(就像文档中的示例一样),它运行得很好,但是如果我想要添加一个单独的自定义视图到布局中并且具有类似Google Play电影应用程序(请参见下面的屏幕截图)中的android.support.v7.widget.SwitchCompat怎么办?

Google Play Movies

我已经尝试了使用actionLayout属性来指定一个自定义布局文件,就像下面的示例代码一样,但该属性被忽略了,因为它没有起作用。

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>

我该如何让这个工作起来?理想情况下,我想在保持使用我的菜单布局的同时添加自定义视图,但是如果不使用粗糙的hack(例如利用支持库生成的现有布局),那么如果没有可能,我想知道最少量代码的解决方案,并且仍然值得过渡到NavigationView


3
当前的NavigationView实现不支持自定义项目。 NavigationView使用一个ListView来填充项目,其中每个项目是一个TextView,目前没有办法定制ListView中的项。 - Wayne
1
有没有办法在菜单项中添加两行文本?我尝试通过actionLayout添加,但它会添加到右侧而不是下方。例如,像Google Drive->升级存储选项显示2行文本。 - Siju
5个回答

43

actionLayout属性现在已经被Android Support Library 23.1支持:

NavigationView提供了一种方便的方式来构建导航抽屉,包括使用menu XML文件创建菜单项的能力。我们扩展了功能,可以通过app:actionLayout或使用MenuItemCompat.setActionView()为项目设置自定义视图。

所以问题中的代码现在应该可以正常工作了。


26
请求使用示例 - krossovochkin
2
只需将属性app:actionLayout="@layout/my_switch_layout"添加到菜单项中即可。我在问题中已经给出了my_switch_layout的示例。 - Tim Rae
4
我尝试使用"app:actionLayout",但它没有起作用。还有其他我可能忽略的东西吗? - Vaibhav Gupta
4
如何使actionLayout在标题后左对齐或右对齐? - jiawen
8
在导航视图中使用时没有用,即使您未指定图标和标题,它仍会为它们留出位置。 - Jemshit Iskenderov
显示剩余4条评论

20

NavigationViewFrameLayout 的子类,可以拥有多个子视图:

你可以向 FrameLayout 添加多个子视图,并使用 android:layout_gravity 属性为每个子视图分配重力来控制它们在 FrameLayout 中的位置。

这意味着你可以将自定义视图添加到你的 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>

谢谢您的回答!不幸的是,我找不到一种方法来确切地将LinearLayout的位置设置在现有(库生成的子布局)正下方。我猜您的意思是我可以使用layout_gravity="bottom"并经验性地调整高度,直到它看起来不错,但这并不是很好。 - Tim Rae
1
这个解决方案就像没有用一样,只使用DrawerLayout而不是NavigationView,我错了吗? - Zorb
5
NavigationView是一个包含ListView的FrameLayout。这种方法不允许向ListView添加自定义菜单项,只能在其顶部显示一些内容,但与ListView的滚动不同步。 - BladeCoder
是的,你说得对,这个解决方案添加了一个静态页脚。顺便说一下,这可能会帮助其他遇到类似问题的人:https://dev59.com/o10a5IYBdhLWcg3wRGrp - Vera Rivotti
你怎么获取它的onclick事件? - Dhinakaran Thennarasu
显示剩余3条评论

10

我遇到了同样的问题,并发现NavigationView的行为会根据以下因素而有所不同:

  • item是否设置android:titleandroid:icon属性
  • 操作布局包含何种视图(例如TextView或其他视图)

在不设置这些属性的情况下,可以完全自定义该项:

<?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>

(请注意,您也可以不设置 android:title,但这会导致在 Android Studio 中出现警告。)

结果:

带有自定义操作布局的导航视图

(这是使用com.android.support:design 27.1.1版本的,其他版本不确定。)


1
这应该是被接受的答案!感谢您! - VIN
这个答案指导我如何向我的菜单项添加额外的布局元素。在我的情况下,是在右侧添加一个额外的图标。现在我想知道:我该如何以编程方式控制每个项目的actionLayout(以及它们的子元素)属性,在我的情况下,要么更改额外图标的图像,要么切换其可见性?也许最终我会从这个问题中得出一个新问题...编辑:说做就做,这里是我的问题 - SebasSBM

6
创建一个使用SwitchCompat的布局,并在菜单项中提及它。
<item android:id="@+id/notification"
        android:title="Notification"
        app:actionLayout="@layout/notify" />`

然后通知布局添加这个内容

<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是关键点,在您的Activity中实现handler,然后它就会起作用。


0

很酷,虽然文档中没有提到,但似乎可以轻松添加这些提供的视图之一,其中包括一个开关 :)https://github.com/mikepenz/MaterialDrawer/tree/develop/library/src/main/java/com/mikepenz/materialdrawer/model不过我想知道是否有支持下至SDK 8的分支呢? :-/ - Tim Rae

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接