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

Google 在设计支持库22.2.0版中引入了 NavigationView,你可以很容易地使用菜单资源创建一个抽屉。

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

如果你能帮忙,我将不胜感激。

102954 次浏览

所有你需要做的就是定义一个 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>

像 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);
}

这个问题的解决方案应该归功于 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);
}

我想要在第一个项目之上和最后一个项目之后的分隔符。使用@Nilesh 解决方案,我必须添加虚拟菜单项,并将启用设置为 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>

编辑:

你可以使用 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>

我认为我有一个更好的解决多个检查项目的问题。使用我的方式,你不必担心改变您的代码时,添加新的部分到您的菜单。 我的菜单看起来就像是 Jared 写的公认的解决方案,不同的是在组中使用 andoid: checkableBehavior = “ 所有”:

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

“ all”的 checkableBehavior 使得可以随意检查/取消检查单个项目,独立于它们所属的组。您只需存储最后一个选中的菜单项。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;
}

尼勒的答案是正确的,除了它有一个缺陷,即复核。

<?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 = “ single”

用唯一的身份证就能解决问题

创建一个像这样的可绘制 < em >  抽屉 _ 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>

并将其作为 应用程序: itemBack = “@draable/pull _ item _ bg” 添加到 NavigationView

<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"/>

开始了。enter image description here

如果你想添加分割器 动态的,你可以像下面这样添加一个空的子菜单:

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

这将添加一个分隔符。

只要确保在使用 menu.getItem(int index)时传入正确的索引即可

简单添加 DeviderItemDecation:

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

我不知道如果这是固定在 API 26 (Android 8)或它是可能的所有时间。我在 Android 编程方面还是个菜鸟。然而,我添加了如下的父组。安卓6物理手机测试,

  1. 我拿到分隔器了
  2. nav_g1nav_g2中选择任何项目将取消选择其他项目。
  3. 由于嵌套组,没有添加额外的填充。
  4. 我没有向监听器添加任何 Java代码

菜单代码

<?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. 正如在 这个答案中提到的,每个组都需要有一个唯一的 ID 来显示分隔符。
  2. 根据 这个回答空间是匹配谷歌材料设计规格。
  3. android:checkableBehavior="single"为父组是必需的,所以问题的多个选择菜单项在 这个的答案(提到在评论饿鬼)不会发生

这是截图

Screenshot of the device screen

通过使用 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"/>

并使用 图层可绘制作为背景。它保留了材料设计纹波覆盖点击。

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

除了以前的答案,如果你确实想要装饰性的分隔符,但是不想因为“可检查的行为”问题而创建多个组-你可以给你所有的组分配相同的组 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>

如果选择的答案对您不起作用,您可以尝试将其添加到 onCreateOptionsMenu中,并给出唯一的组 id:

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

调用需要 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)




}