如何在新的NavigationView中创建一个简单的分隔符?

时间:2015-06-03 16:06:21

标签: android navigation-drawer android-support-library android-design-library navigationview

Google在设计支持库22.2.0版中引入了Sub A,您可以使用菜单资源轻松创建抽屉。

如何在两个项目之间创建简单的分隔线?对项目进行分组不起作用。创建子项目部分会创建一个分隔线,但它需要一个我不想要的标题。

任何帮助都将不胜感激。

14 个答案:

答案 0 :(得分:298)

您需要做的就是定义一个带有唯一ID group,如果群组有不同的ID,我会检查实施情况,它会创建一个分隔符。

示例菜单,创建分隔符:

<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:context=".MainActivity">

    <group android:id="@+id/grp1" android:checkableBehavior="single" >
        <item
            android:id="@+id/navigation_item_1"
            android:checked="true"
            android:icon="@drawable/ic_home"
            android:title="@string/navigation_item_1" />
    </group>

    <group android:id="@+id/grp2" android:checkableBehavior="single" >
        <item
            android:id="@+id/navigation_item_2"
            android:icon="@drawable/ic_home"
            android:title="@string/navigation_item_2" />
    </group>
</menu>

答案 1 :(得分:44)

像这样创建一个可绘制的 drawer_item_bg.xml

    <layer-list xmlns:android="http://schemas.android.com/apk/res/android">

    <item>
        <shape android:shape="rectangle" >
            <solid android:color="#F4F4F4" />
        </shape>
    </item>

    <item android:top="-2dp" android:right="-2dp" android:left="-2dp">
        <shape>
            <solid android:color="@android:color/transparent" />
            <stroke
                android:width="1dp"
                android:color="#EAEAEA" />
        </shape>
        <!--
        android:dashGap="10px"
                android:dashWidth="10px"
                -->
    </item>

</layer-list>

并将其作为 app添加到NavigationView:itemBackground =&#34; @ drawable / drawer_item_bg&#34;

<android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:background="#F4F4F4"
        android:layout_gravity="start"
        android:fitsSystemWindows="false"
        app:menu="@menu/activity_main_drawer"
        app:itemBackground="@drawable/drawer_item_bg"/>

我们走了...... screenshot

答案 2 :(得分:15)

简单添加DeviderItemDecoration:

NavigationView navigationView = (NavigationView) findViewById(R.id.navigation);
NavigationMenuView navMenuView = (NavigationMenuView) navigationView.getChildAt(0);
navMenuView.addItemDecoration(new DividerItemDecoration(MainActivity.this,DividerItemDecoration.VERTICAL));

看起来像这样:

enter image description here

答案 3 :(得分:11)

我认为我有一个更好的解决方案来解决多个检查项目的问题。使用我的方式,在向菜单添加新部分时,不必担心更改代码。 我的菜单看起来就像是由Jared编写的公认解决方案,区别在于使用andoid:checkableBehavior =&#34; all &#34;在群体上:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <group android:id="@+id/first_section" android:checkableBehavior="all">
        <item
            android:id="@+id/frontpage"
            android:icon="@drawable/ic_action_home_24dp_light_blue"
            android:title="@string/drawer_frontpage" />
        <item
            android:id="@+id/search"
            android:icon="@drawable/ic_search"
            android:title="@string/drawer_search" />
    </group>
    <group android:id="@+id/second_section" android:checkableBehavior="all">
        <item
            android:id="@+id/events"
            android:icon="@drawable/ic_maps_local_movies_24dp_light_blue"
            android:title="@string/drawer_events" />
    </group>
</menu>

&quot; all&#39;的checkableBehavior可以随意选中/取消选中单个项目,与其所属的组无关。您只需存储最后检查的menuitem。 java代码如下所示:

private MenuItem activeMenuItem;

@Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
    // Update selected/deselected MenuItems
    if (activeMenuItem != null)
        activeMenuItem.setChecked(false);
    activeMenuItem = menuItem;
    menuItem.setChecked(true);

    drawerLayout.closeDrawers();
    return true;
}

答案 4 :(得分:11)

您可以使用app:itemBackground

通过XML设置菜单项背景,轻松添加分隔符
<android.support.design.widget.NavigationView
    android:id="@id/drawer_navigation_view"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:fitsSystemWindows="true"
    app:menu="@menu/all_navigation_menu"
    app:itemIconTint="@color/colorPrimary"
    app:itemBackground="@drawable/bg_drawer_item"
    android:background="@color/default_background"/>

并使用 LayerDrawable 作为背景。它为点击保留了材料设计纹波覆盖。

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="rectangle">
            <solid android:color="@color/white"/>
        </shape>
    </item>
    <item android:left="@dimen/activity_horizontal_margin">
        <shape android:shape="rectangle">
            <solid android:color="@color/divider"/>
        </shape>
    </item>
    <item android:bottom="1dp">
        <shape android:shape="rectangle">
            <solid android:color="@color/white"/>
        </shape>
    </item>
</layer-list>

结果:

enter image description here

答案 5 :(得分:8)

像Nilesh的答案那样制作不同的小组确实会在两者之间形成一个分隔符 在导航抽屉中创建两个已检查项目的问题。

我处理这个问题的一个简单方法是:

    public boolean onNavigationItemSelected(final MenuItem menuItem) {

    //if an item from extras group is clicked,refresh NAV_ITEMS_MAIN to remove previously checked item
    if (menuItem.getGroupId() == NAV_ITEMS_EXTRA) {


        navigationView.getMenu().setGroupCheckable(NAV_ITEMS_MAIN, false, true);
        navigationView.getMenu().setGroupCheckable(NAV_ITEMS_EXTRA, true, true);
       }else{

        navigationView.getMenu().setGroupCheckable(NAV_ITEMS_MAIN, true, true);
        navigationView.getMenu().setGroupCheckable(NAV_ITEMS_EXTRA, false, true);


    }
    //Update highlighted item in the navigation menu
    menuItem.setChecked(true);
}

答案 6 :(得分:7)

我不确定这是否已在API 26 (Android 8)中修复,或者它始终是可能的。我仍然是Android编程的菜鸟。但是我添加了如下的父组。在Android 6手机上测试,

  1. 我有分隔符
  2. nav_g1nav_g2中选择任何项目都会取消选择其他项目。
  3. 由于嵌套组而没有添加额外的填充。
  4. 我没有向听众添加任何Java代码
  5. 菜单代码

    <?xml version="1.0" encoding="utf-8"?>
    <menu xmlns:android="http://schemas.android.com/apk/res/android">
        <group android:checkableBehavior="single">
            <group
                android:id="@+id/nav_g1"
                android:checkableBehavior="single">
                <item
                    android:id="@+id/nav_1"
                    android:icon="@drawable/ic_menu_share"
                    android:title="@string/nav_1"/>
                <item
                    android:id="@+id/nav_2"
                    android:icon="@drawable/ic_menu_share"
                    android:title="@string/nav_2"/>
            </group>
            <group
                android:id="@+id/nav_g2"
                android:checkableBehavior="single">
                <item
                    android:id="@+id/nav_3"
                    android:icon="@drawable/ic_menu_share"
                    android:title="@string/nav_3"/>
                <item
                    android:id="@+id/nav_4"
                    android:icon="@drawable/ic_menu_share"
                    android:title="@string/nav_4"/>
            </group>
        </group>
        <item android:title="Actions">
            <menu>
                <item
                    android:id="@+id/nav_7"
                    android:icon="@drawable/ic_menu_share"
                    android:title="@string/nav_7"/>
                <item
                    android:id="@+id/nav_8"
                    android:icon="@drawable/ic_menu_share"
                    android:title="@string/nav_8"/>
            </menu>
        </item>
    </menu>
    

    备注

    1. 正如this中所述,每个小组都需要有一个唯一的ID才能显示分隔符。
    2. 根据this,答案空间与Google资料设计规范相匹配。
    3. 需要android:checkableBehavior="single"为父组,因此this中的多个所选菜单项的问题(由hungryghost评论中提及)不会发生
    4. 这是截图

      Screenshot of the device screen

答案 7 :(得分:5)

我想在第一个项目之上和最后一个项目之后使用分隔线。使用@Nilesh解决方案我不得不添加虚拟菜单项并将enabled设置为false,感觉非常脏。如果我想在我的菜单中做其他很酷的东西呢?

我注意到NavigationView扩展了FrameLayout,因此您可以将自己的内容放入其中,就像使用FrameLayout一样。然后我设置一个空的菜单xml,以便它只显示我的自定义布局。我知道这可能违背了谷歌希望我们采取的路径,但如果你想要一个真正的自定义菜单,这是一个简单的方法。

<!--Note: NavigationView extends FrameLayout so we can put whatever we want in it.-->
<!--I don't set headerLayout since we can now put that in our custom content view-->
<android.support.design.widget.NavigationView
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:fitsSystemWindows="true"
    app:menu="@menu/empty_menu">

    <!--CUSTOM CONTENT-->
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <!-- CUSTOM HEADER -->
        <include
            android:id="@+id/vNavigationViewHeader"
            layout="@layout/navigation_view_header"/>

        <!--CUSTOM MENU-->
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:layout_below="@+id/vNavigationViewHeader">

            <View style="@style/NavigationViewLineSeperator"/>

            <Button android:text="Option 1"/>

            <View style="@style/NavigationViewLineSeperator"/>

            <Button android:text="Option 2"/>

            <View style="@style/NavigationViewLineSeperator"/>

        </LinearLayout>
    </RelativeLayout>
</android.support.design.widget.NavigationView>

这是风格

<style name="NavigationViewLineSeperator">
        <item name="android:background">@drawable/line_seperator</item>
        <item name="android:layout_width">match_parent</item>
        <item name="android:layout_height">1dp</item>
</style>

可绘制

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">

    <solid android:color="@color/white"/>
    <size android:width="100sp"
          android:height="1sp" />
</shape>

菜单

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
</menu>

编辑:

您可以使用带有drawable的TextView代替Buttons,它可以模仿原始菜单项:

 <TextView
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:text="@string/menu_support"
     android:drawableLeft="@drawable/menu_icon_support"
     style="@style/MainMenuText" />

// style.xml
<style name="MainMenuText">
    <item name="android:drawablePadding">12dp</item>
    <item name="android:padding">10dp</item>
    <item name="android:gravity">center_vertical</item>
    <item name="android:textColor">#fff</item>
</style>

答案 8 :(得分:1)

应该向Zorawar提供解决方案,很抱歉重复答案,但无法在评论中添加如此多的格式化文本。

Zorawar的解决方案有效,代码可以这样改进:

public void onNavigationItemSelected(int groupId) {

    //if an item from extras group is clicked,refresh NAV_ITEMS_MAIN to remove previously checked item
    navigationView.getMenu().setGroupCheckable(NAV_ITEMS_MAIN, (groupId == NAV_ITEMS_MAIN), true);
    navigationView.getMenu().setGroupCheckable(NAV_ITEMS_EXTRA, (groupId == NAV_ITEMS_EXTRA), true);


    //Update highlighted item in the navigation menu
    menuItem.setChecked(true);
}

答案 9 :(得分:1)

调用需要 API 级别 28:

就用

 menu?.setGroupDividerEnabled(true)

在 onCreateOptionsMenu 函数中

示例:

override fun onCreateOptionsMenu(menu: Menu?): Boolean {

        menuInflater.inflate(R.menu.main_menu, menu)

        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.P) {
            menu?.setGroupDividerEnabled(true)
        }
        
        return super.onCreateOptionsMenu(menu)


    }

答案 10 :(得分:0)

Nileh的回答是对的,除了它有一个双重检查的缺陷。

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <group android:checkableBehavior="single" android:id="@+id/grp1">
        <item
            android:id="@+id/nav_register_customer"
            android:icon="@drawable/ic_menu_camera"
            android:checkableBehavior="none"
            android:title="Register Customer" />
    </group>
    <group  android:id="@+id/grp2"
        android:checkableBehavior="single"  >
        <item
            android:id="@+id/nav_slideshow"
            android:icon="@drawable/ic_menu_slideshow"
            android:checkableBehavior="none"
            android:title="Slideshow" />
    </group>
</menu>

所以使用

  

机器人:checkableBehavior = “单”

具有唯一ID的

将解决问题

答案 11 :(得分:0)

如果你想动态添加divider ,你可以像这样添加一个空的SubMenu:

Menu menu = navigationView.getMenu();
menu.addSubMenu(" ").add(" ");

这会添加一个分隔符。

使用menu.getItem(int index)

时,请务必传入正确的索引

答案 12 :(得分:0)

除了以前的答案,如果您确实想要装饰性分隔符但又由于“可检查的行为”问题而不想创建多个组,则可以为所有组分配相同的组ID。

示例:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group
    android:id="@+id/group_nav_common" <!-- New group id-->
    android:checkableBehavior="single">

    <item
        android:id="@+id/menu_item_nav_home"
        android:icon="@drawable/ic_home_black_24dp"
        android:title="@string/nav_menu_main" />
    <item
        android:id="@+id/menu_item_nav_articles"
        android:icon="@drawable/ic_art_track_black_24dp"
        android:title="@string/latest_news" />

    <item
        android:id="@+id/menu_item_nav_group_categories"
        android:title="@string/nav_menu_sections">
        <menu>
            <group
                android:id="@id/group_nav_common" <!-- Existing group id -->
                android:checkableBehavior="single">
                <!-- Programmatically populated section -->
            </group>
        </menu>
    </item>

    <item
        android:id="@+id/menu_item_nav_group_sites"
        android:title="@string/nav_menu_sites">
        <menu>
            <group
                android:id="@id/group_nav_common" <!-- Existing group id -->
                android:checkableBehavior="single">
                <item
                    android:id="@+id/menu_item_nav_select_site"
                    android:icon="@drawable/ic_account_balance_black_24dp"
                    android:title="@string/nav_menu_select_site" />
            </group>
        </menu>
    </item>
</group>

答案 13 :(得分:0)

如果所选答案不适合您,除了提供唯一的组ID外,您可能还想尝试将其添加到onCreateOptionsMenu中。

if (Build.VERSION.SDK_INT >= 28) {
    menu.setGroupDividerEnabled(true)
}