Bagaimana cara membuat pembagi sederhana di NavigationView baru?

154

Google memperkenalkan NavigationView di Perpustakaan Dukungan Desain versi 22.2.0 yang dengannya Anda dapat membuat laci dengan sangat mudah menggunakan sumber daya menu.

Bagaimana saya bisa membuat garis pembagi sederhana antara dua item? Mengelompokkan item tidak berfungsi. Membuat bagian sub item memang membuat garis pembagi, tetapi membutuhkan judul, yang tidak saya inginkan.

Bantuan apa pun akan dihargai.

Longi
sumber
Seperti yang dinyatakan dalam komentar untuk itu, masalah dengan jawaban yang diterima adalah, bahwa perilaku yang dapat diperiksa tidak bekerja di beberapa kelompok (paralel). Untuk menghindari hal ini, jangan membuat grup paralel, tetapi gunakan sub menu atau sub grup untuk mendapatkan pembagi Anda seperti yang dijelaskan dalam jawaban saya di sini: stackoverflow.com/questions/30766919/…
Hingga

Jawaban:

319

Yang perlu Anda lakukan adalah mendefinisikan groupdengan ID unik , saya telah memeriksa implementasinya jika grup memiliki id berbeda, itu akan membuat pembagi.

Menu contoh, membuat pemisah:

<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>
NJ
sumber
9
Bertanya-tanya mengapa ini (sejauh yang saya tahu) tidak didokumentasikan. Saya pikir itu akan banyak ditanyakan. Terima kasih!
Gaëtan
16
Satu masalah dengan pendekatan ini adalah yang setCheckedtampaknya bekerja di tingkat kelompok. Jika Anda memilih item di Grup A, lalu buka laci lagi dan pilih item di Grup B, kedua item akan tetap disorot. Mungkin Google akan memperbaiki perilaku ini di rilis berikutnya, tetapi untuk saat ini, itulah kerugian menggunakan beberapa grup dengan NavigationView.
hungryghost
3
Bagus. Tentang pemeriksaan ganda, cobalah android:checkableBehavior="none"untuk grup kedua Anda (yang merupakan tindakan, bukan navigasi, saya kira)
espinchi
12
Lucunya, jika Anda menghapus id dari groupitu akan mengkompilasi dan menjalankan tetapi pembagi disembunyikan.
Vahid Amiri
5
Ini tidak bekerja untuk saya juga. Saya ingin garis di antara grup menu, bukan setelah setiap item.
Rich Morey
54

buat drawer_item_bg.xml yang bisa digambar seperti ini,

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

dan menambahkannya ke NavigationView sebagai aplikasi: itemBackground = "@ drawable / 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"/>

dan di sini kita pergi ...masukkan deskripsi gambar di sini

vbp
sumber
1
ini berfungsi, tetapi itu juga menghapus padding kiri ikon item. setidaknya dalam kode saya, bukan dalam tangkapan layar Anda karena beberapa alasan
luky
@vbp Saya perlu batas atas untuk anak pertama, batas bawah untuk anak lain. Bagaimana saya bisa mencapainya. Ini adalah sesuatu yang mirip dengan anak id.first pertama di css
Prab
@Prabs mempertimbangkan untuk menggunakan tampilan fragmen, daur ulang, atau kustom alih-alih NavigationView untuk kustomisasi yang lebih baik
vbp
1
Saya telah melakukan navMenuView.addItemDecoration(new DividerItemDecoration(NavigationViewActivity.this, DividerItemDecoration.VERTICAL));untuk perbatasan item sempurna
Prab
19

Sederhana tambahkan DeviderItemDecoration:

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

Ini terlihat seperti ini:

masukkan deskripsi gambar di sini

SANAT
sumber
Bisakah saya mengubah ketinggian addItemDecorationbaris ke 1px?
Prab
Terima kasih, solusi Anda berhasil untuk saya. Saya menghargai. Bro satu pertanyaan lagi dengan ini. Apakah mungkin untuk menghapus batas atas untuk item pertama dan menetapkan batas hanya ke bagian bawah item?
viper
@ viper silakan lihat ini: bignerdranch.com/blog/…
SANAT
1
Pembagi semacam itu untuk setiap item tidak mengikuti Material Guyidelines
Boris Ruzanov
19

Anda dapat menambahkan pembagi dengan mudah dengan mengatur Latar Belakang Item Menu melalui XML menggunakan 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"/>

Dan gunakan LayerDrawable sebagai latar belakang. Ini melindungi overlay desain material untuk klik.

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

Hasil:

masukkan deskripsi gambar di sini

Stanislav Perchenko
sumber
2
tampaknya menjadi jawaban terbaik dan tidak ada grup yang terlibat
Michał Ziobro
Bagaimana jika Anda ingin menggunakan warna latar belakang khusus untuk item yang dipilih?
ataravati
Saya memiliki kesalahan pada <shape>: Elemen tidak diizinkan di sini
Sébastien REMY
11

Saya pikir saya punya solusi yang lebih baik untuk masalah beberapa item yang diperiksa. Dengan menggunakan cara saya, Anda tidak perlu khawatir tentang mengubah kode Anda saat menambahkan bagian baru ke menu Anda. Menu saya terlihat seperti solusi yang diterima yang ditulis oleh Jared, dengan perbedaan menggunakan andoid: checkableBehavior = " all " pada grup:

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

Perilaku checkable 'all' memungkinkan untuk memeriksa / menghapus centang item tunggal sesuka hati, terlepas dari grup mana mereka berasal. Anda hanya perlu menyimpan menuit yang terakhir diperiksa. Kode java terlihat seperti ini:

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;
}
kekusutan
sumber
8

Membuat grup yang berbeda seperti jawaban Nilesh memang membuat pembagi di antara Tapi menciptakan masalah dua item yang diperiksa di laci nav.

Cara sederhana bagaimana saya menangani ini adalah:

    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 Sachdev
sumber
Lebih sederhana:android:checkableBehavior="none"
espinchi
2
@espinchi - Itu tidak akan berfungsi jika grup lain berisi item menu navigasi. Solusi ini hanya bisa digunakan untuk tindakan. Latihan UX yang tidak bagus
Mushtaq Jameel
Luar biasa! Mungkin lebih jelas jika Anda mengubah konstanta yang tidak terdefinisi NAV_ITEMS_MAIN dan NAV_ITEMS_EXTRA Anda dengan R.id.nav_items_group_main atau R.id.nav_items_group_extra dan menambahkan XML yang diperlukan untuk contoh Anda
ChrisPrime
IS onNavigationItemSelected (menuItem menuItem final) {Metode default ?? di mana saya harus melakukan kode ini?
John
dan apa itu NAV_ITEMS_MAIN ??
John
8

Saya tidak yakin apakah ini sudah diperbaiki API 26 (Android 8)atau mungkin sepanjang waktu. Saya masih noob dalam pemrograman Android. Namun saya menambahkan grup induk seperti di bawah ini. Menguji pada ponsel Android 6 fisik,

  1. Saya punya pembagi
  2. Memilih item apa saja dari salah satu nav_g1atau nav_g2akan membatalkan pilihan item lainnya.
  3. Tidak ada bantalan tambahan yang ditambahkan karena grup bersarang.
  4. Saya tidak menambahkan Javakode apa pun ke pendengar

Kode Menu

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

Catatan

  1. Sebagaimana disebutkan dalam jawaban ini, setiap grup harus memiliki ID unik untuk menunjukkan pembagi.
  2. Sesuai ini jawaban ruang yang cocok dengan google spesifikasi desain material.
  3. Memiliki android:checkableBehavior="single"untuk kelompok orang tua diperlukan sehingga masalah beberapa item menu yang dipilih dalam ini jawaban (disebutkan dalam komentar dengan hungryghost) tidak terjadi

Dan inilah screenshotnya

Tangkapan layar layar perangkat

AaA
sumber
5

Saya ingin pembagi di atas item pertama dan setelah item terakhir. Menggunakan solusi @Nilesh saya harus menambahkan item menu dummy dan mengatur diaktifkan ke false yang terasa sangat kotor. Plus bagaimana jika saya ingin melakukan hal-hal keren lainnya di menu saya?

Saya perhatikan NavigationView memperluas FrameLayout sehingga Anda dapat memasukkan konten Anda sendiri seperti yang Anda lakukan untuk FrameLayout. Saya kemudian mengatur menu kosong xml sehingga hanya menampilkan tata letak khusus saya. Saya mengerti bahwa ini mungkin bertentangan dengan jalur yang Google inginkan untuk kami ambil, tetapi jika Anda menginginkan menu yang benar-benar khusus, ini adalah cara mudah untuk melakukannya.

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

Inilah gayanya

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

Dan mudah digambar

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

Dan menunya

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

edit:

Alih-alih Tombol Anda dapat menggunakan TextView dengan drawable yang meniru item menu asli terlihat:

 <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>
Justin Fiedler
sumber
1
terima kasih, tampaknya cara paling nyaman untuk memiliki tampilan khusus sebagai item menu
Jan Rabe
saya menggunakan solusi ini juga karena itu memungkinkan saya lebih mudah mengatur font item kustom dan mengubah warna pembagi
luky
1

Penghargaan harus diberikan kepada Zorawar untuk solusinya, Maaf karena menduplikasi jawabannya tetapi tidak dapat menambahkan begitu banyak teks yang diformat dalam komentar.

Solusi Zorawar berfungsi, kode dapat diperbaiki seperti:

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);
}
Mushtaq Jameel
sumber
apa itu NAV_ITEMS_MAIN dan NAV_ITEMS_EXTRA dan groupid ??
John
Mereka adalah konstanta untuk group_id
Mushtaq Jameel
0

Jawaban Nileh benar, Kecuali ia memiliki satu kekurangan pengecekan ganda.

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

Jadi menggunakan

android: checkableBehavior = "single"

dengan id unik akan menyelesaikan masalah

Ajji
sumber
0

Jika Anda ingin menambahkan pembagi secara dinamis , Anda bisa menambahkan SubMenu kosong seperti ini:

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

ini akan menambah pembagi.

pastikan untuk lulus dalam indeks yang tepat saat menggunakan menu.getItem(int index)

Moh Mah
sumber
0

Selain jawaban sebelumnya jika Anda menginginkan pemisah dekoratif tetapi tidak ingin membuat beberapa grup karena masalah "perilaku yang dapat diperiksa" - Anda dapat menetapkan id grup yang sama untuk semua grup Anda.

Contoh:

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

ievgen
sumber
0

Jika jawaban yang dipilih tidak berfungsi untuk Anda, Anda mungkin ingin mencoba menambahkan ini onCreateOptionsMenusebagai tambahan untuk memberikan id grup unik:

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