it-swarm.com.ru

Как создать простой разделитель в новом NavigationView?

Google представил NavigationView в Библиотеке поддержки проектирования версии 22.2.0, с помощью которой вы можете очень легко создать ящик, используя ресурс меню.

Как я могу создать простую разделительную линию между двумя элементами? Группировка предметов не сработала. Создание раздела подэлементов создает разделительную линию, но требует заголовка, который мне не нужен.

Любая помощь будет оценена.

130
Longi

Все, что вам нужно сделать, это определить group с уникальным идентификатором , я проверил реализацию, если группа имеет разные идентификаторы, она создаст разделитель.

Пример меню, создающего разделитель:

<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>
285
N J

создать нарисованный box_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>

и добавьте его в NavigationView как app: itemBackground = "@ drawable/box_item_bg"

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

и здесь мы идем ... скриншот

42
vbp

Просто добавьте 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

16
SANAT

Я думаю, что у меня есть еще лучшее решение проблемы нескольких проверенных пунктов. Используя мой способ, вам не нужно беспокоиться об изменении кода при добавлении новых разделов в ваше меню ........ Мое меню выглядит так же, как принятое решение, написанное Джаредом, с разницей в использовании andoid: checkableBehavior = " all "по группам:

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

CheckableBehavior of «all» позволяет проверять/снимать флажки с отдельных элементов по желанию независимо от того, к какой группе они принадлежат. Вам просто нужно сохранить последний проверенный пункт меню. 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;
}
11
plexus

Вы можете легко добавить разделители, установив фон элемента меню через XML с помощью app:itemBackground

<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

9
Stanislav Perchenko

Создание разных групп, таких как ответ Нилеша, делает разделитель между Но Создает проблему двух проверенных элементов в навигационном ящике.

Простой способ, как я справился с этим, был: 

    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);
}
8
Zorawar Sachdev

Я не уверен, исправлено ли это в API 26 (Android 8) или это было возможно все время. Я все еще новичок в программировании Android. Однако я добавил родительские группы, как показано ниже. Тестирование на физическом телефоне Android 6, 

  1. У меня есть делитель 
  2. Выбор любого элемента из nav_g1 или nav_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. Как упоминалось в этом ответе, каждая группа должна иметь уникальный идентификатор, чтобы показать разделитель.
  2. Согласно это answer пробелы соответствуют спецификациям дизайна материалов Google.
  3. Наличие Android:checkableBehavior="single" для родительской группы является обязательным, поэтому проблема множественных выбранных пунктов меню в this answer (упоминается в комментариях Hungryghost) не возникает

И вот скриншот

 Screenshot of the device screen

6
AaA

Я хотел разделители над первым пунктом и после последнего элемента. Используя решение @Nilesh, мне пришлось добавить фиктивные пункты меню и установить для false значение false, которое было очень грязным. Плюс, что если я захочу сделать другие интересные вещи в моем меню?

Я заметил, что NavigationView расширяет FrameLayout, так что вы можете помещать в него свой собственный контент, как и для FrameLayout. Затем я устанавливаю пустое меню xml, чтобы оно показывало только мой пользовательский макет. Я понимаю, что это, вероятно, идет вразрез с тем, как Google хочет, чтобы мы пошли по нему, но если вы хотите действительно индивидуальное меню, это простой способ сделать это.

<!--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 с drawable, который имитирует внешний вид оригинальных пунктов меню:

 <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>
5
Justin Fiedler

Кредит должен пойти в 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);
}
1
Mushtaq Jameel

Если вы хотите добавить разделитель динамически , вы можете просто добавить пустое SubMenu следующим образом:

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

это добавит разделитель.

просто обязательно передайте правильный индекс при использовании menu.getItem(int index) 

0
Mohammad Mahtabi

Ответ Ниле верен, за исключением того, что у него есть один недостаток двойной проверки.

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

Итак, используя 

Android: checkableBehavior = "сингл"

с уникальным идентификатором решит проблему

0
Ajji

Если выбранный ответ не работает для вас, вы можете попробовать добавить это к onCreateOptionsMenu, чтобы дать уникальный идентификатор группы:

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

В дополнение к предыдущим ответам, если вы хотите использовать декоративные разделители, но не хотите создавать несколько групп из-за проблем с «проверяемым поведением», вы можете назначить один и тот же идентификатор группы всем своим группам.

Пример:

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

0
ievgen