Як створити простий подільник у новому NavigationView?


154

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

Як я можу створити просту лінію розділення між двома елементами? Групування елементів не вийшло. Створення розділу підпунктів створює розділову лінію, але вона вимагає заголовка, якого я не хочу.

Будь-яка допомога буде вдячна.


Як зазначається в коментарях до цього, проблема з прийнятою відповіддю полягає в тому, що поведінка, що перевіряється, не працює у кількох (паралельних) групах. Щоб уникнути цього, не створюйте паралельних груп, а використовуйте підменю чи підгрупи, щоб отримати роздільники, як описано в моїй відповіді тут: stackoverflow.com/questions/30766919/…
до

Відповіді:


319

Все , що вам потрібно зробити , це визначить 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>

9
Цікаво, чому це (наскільки я знаю) не задокументоване. Думаю, про це буде запитуватися багато. Дякую!
Гаетан

16
Одна з проблем такого підходу полягає в тому, що, setCheckedздається, працює на рівні групи. Якщо ви вибрали предмет у групі A, потім знову відкрийте шухляду та виберіть елемент у групі B, обидва елементи залишаться виділеними. Можливо, Google виправить цю поведінку в наступному випуску, але поки що це недолік використання декількох груп з NavigationView.
голодний

3
Чудово. Про подвійний перевірений, спробуйте android:checkableBehavior="none"для своєї другої групи (це дії, а не навігація, я вважаю)
espinchi

12
Смішна річ, якщо ви вилучите ідентифікатор з groupнього, він складеться і запуститься, але роздільники приховані.
Вахід Амірі

5
Це не працює і для мене. Я хотів, щоб рядки між групами меню були не після кожного пункту.
Річ Морі

54

створити черпальний 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>

і додайте його до NavigationView як додаток: itemBackground = "@ dravable / drawer_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"/>

а ось і ми...введіть тут опис зображення


1
це працює, але він також видаляє ліву підкладку піктограми елемента. принаймні в моєму коді, а не на екрані з якихось причин
Luky

@vbp Мені потрібна верхня межа для першої дитини, нижня межа для іншої дитини. Як я міг досягти. Це щось схоже на id.first child in css
Prabs

@Prabs розглядають можливість використання фрагмента, перегляду рециркуляторів чи спеціальних представлень замість NavigationView для кращого налаштування
vbp

1
Я зробив navMenuView.addItemDecoration(new DividerItemDecoration(NavigationViewActivity.this, DividerItemDecoration.VERTICAL));для ідеального кордону пункту
Prabs

19

Просте додавання DeviderItemDecoration:

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

Це виглядає приблизно так:

введіть тут опис зображення


Чи можу я змінити висоту addItemDecorationлінії на 1px?
Прабс

Дякую, що ваше рішення працювало на мене. Я ціную. Ще одне питання з цим. Чи можливо видалити верхню межу для першого елемента та встановити межі лише в нижній частині елементів?
гадюка

@viper, будь ласка, зверніться до цього: bignerdranch.com/blog/…
SANAT

1
Такий подільник для кожного елемента не дотримується Матеріальні рекомендації
Борис Рузанов,

19

Ви можете легко додати роздільники, встановивши пункт "Пункт меню" за допомогою 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"/>

І використовуйте LayerDravable як фон. Він зберігає накладне руйнування матеріалу для натискань.

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

Результат:

введіть тут опис зображення


2
Здається, найкраща відповідь, і жодна група не бере участь
Міхал Зібро

Що робити, якщо ви хочете використовувати спеціальний колір фону для вибраного елемента?
ataravati

У мене помилка на <shape>: Елемент тут не дозволений
Sébastien REMY

11

Я думаю, що у мене є ще краще рішення проблеми декількох перевірених предметів. Використовуючи мій спосіб, вам не потрібно турбуватися про зміну коду під час додавання нових розділів у меню. Моє меню виглядає так, як прийняте рішення, написане Джаредом, з різницею використання 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>

Перевірений поведінка "всіх" дає можливість перевірити / зняти прапорець по одній позиції за бажанням, незалежно від того, до якої групи вони належать. Вам просто потрібно зберегти останній перевірений меню. 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;
}

8

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

Простий спосіб, як я впорався з цим, був:

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

Ще простіше:android:checkableBehavior="none"
espinchi

2
@espinchi - Це не спрацює, якщо інші групи містять елементи навігаційного меню. Це рішення може працювати лише для дій. Не хороша практика у сфері UX
Mushtaq Jameel

Відмінно! Це може бути зрозуміліше, якщо ви змінили свої невизначені константи NAV_ITEMS_MAIN та NAV_ITEMS_EXTRA на R.id.nav_items_group_main або R.id.nav_items_group_extra та додали потрібний XML до свого прикладу
ChrisPrime

IS onNavigationItemSelected (остаточне menuItem menuItem) {метод за замовчуванням ?? де мені робити цей код?
Джон

а що таке NAV_ITEMS_MAIN ??
Джон

8

Я не впевнений, чи це зафіксовано, API 26 (Android 8)чи це було можливо весь час. Я все ще noob в програмуванні 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. Відповідно до цього простору відповіді відповідні специфікації дизайну матеріалів Google.
  3. Необхідно мати android:checkableBehavior="single"батьківську групу, щоб проблема з декількома вибраними пунктами меню у цій відповіді (згаданих у коментарях Hungryghost) не сталася

А ось скріншот

Знімок екрана пристрою


5

Я хотів роздільників вище першого пункту та після останнього. Використовуючи рішення @Nilesh, мені довелося додати пустуючі пункти меню та встановити функцію 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 з графічним малюнком, який імітує зовнішній вигляд пунктів меню:

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

1
дякую, мабуть, найзручніший спосіб відображення користувальницьких переглядів як пунктів меню
Ян Рабе

я використовую це рішення ще й тому, що це дозволяє мені легше встановити спеціальний шрифт елементів і змінити колір дільника
luky

1

Кредит повинен отримати Зоравар за рішення, вибачте за дублювання відповіді, але не зміг додати стільки форматованого тексту в коментар.

Рішення 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);
}

що таке NAV_ITEMS_MAIN і NAV_ITEMS_EXTRA та groupid ??
Джон

Вони є константами групи_id
Муштак

0

Відповідь Ніла правильна, за винятком того, що вона має один недолік подвійної перевірки.

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

Якщо ви хочете динамічно додати роздільник , ви можете просто додати порожній SubMenu так:

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

це додасть роздільник.

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


0

На додаток до попередніх відповідей, якщо ви хочете декоративні роздільники, але не хочете створювати декілька груп через проблеми "поведінки, що можна перевірити" - ви можете призначити однаковий ідентифікатор групи для всіх своїх груп.

Приклад:

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

Якщо вибрана відповідь не працює для вас, ви можете спробувати додати її до onCreateOptionsMenuтого, щоб надати унікальний ідентифікатор групи:

if (Build.VERSION.SDK_INT >= 28) {
    menu.setGroupDividerEnabled(true)
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.