Wie erstelle ich einen einfachen Teiler in der neuen Navigationsansicht?


153

Google stellte die NavigationView Version 22.2.0 der Design Support Library eingeführt, mit der Sie mithilfe einer Menüressource ganz einfach eine Schublade erstellen können.

Wie kann ich eine einfache Trennlinie zwischen zwei Elementen erstellen? Das Gruppieren der Elemente hat nicht funktioniert. Das Erstellen eines Unterelementabschnitts erstellt zwar eine Trennlinie, erfordert jedoch einen Titel, den ich nicht möchte.

Jede Hilfe wäre dankbar.


Wie in den Kommentaren angegeben, besteht das Problem mit der akzeptierten Antwort darin, dass das überprüfbare Verhalten nicht über mehrere (parallele) Gruppen hinweg funktioniert. Um dies zu vermeiden, erstellen Sie keine parallelen Gruppen, sondern verwenden Sie Untermenüs oder Untergruppen, um Ihre Teiler zu erhalten, wie in meiner Antwort hier beschrieben: stackoverflow.com/questions/30766919/…
Bis

Antworten:


319

Alles, was Sie tun müssen, ist eine groupmit einer eindeutigen ID zu definieren . Ich habe die Implementierung überprüft. Wenn die Gruppe unterschiedliche IDs hat , wird ein Teiler erstellt.

Beispielmenü zum Erstellen des Trennzeichens:

<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
Ich frage mich, warum dies (soweit ich weiß) nicht dokumentiert ist. Ich denke, es wird viel gefragt. Vielen Dank!
Gaëtan

16
Das einzige Problem bei diesem Ansatz ist, dass setCheckedes auf Gruppenebene zu funktionieren scheint. Wenn Sie einen Artikel in Gruppe A auswählen, die Schublade erneut öffnen und einen Artikel in Gruppe B auswählen, bleiben beide Artikel hervorgehoben. Möglicherweise wird Google dieses Verhalten in der nächsten Version beheben, aber im Moment ist dies der Nachteil der Verwendung mehrerer Gruppen mit NavigationView.
Hungerghost

3
Toll. Versuchen Sie es android:checkableBehavior="none"mit Ihrer zweiten Gruppe (das sind Aktionen, keine Navigation, nehme ich an)
espinchi

12
Lustige Sache, wenn Sie die ID aus der entfernen group, wird sie kompiliert und ausgeführt, aber die Teiler sind versteckt.
Vahid Amiri

5
Das funktioniert auch bei mir nicht. Ich wollte Zeilen zwischen den Menügruppen, nicht nach jedem Punkt.
Rich Morey

54

Erstellen Sie eine zeichnbare drawer_item_bg.xml wie folgt :

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

und fügen Sie es als App zu NavigationView hinzu : 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"/>

und es geht los...Geben Sie hier die Bildbeschreibung ein


1
Dies funktioniert, entfernt jedoch auch die linke Auffüllung des Elementsymbols. Zumindest in meinem Code, aus irgendeinem Grund nicht in Ihrem Screenshot
luky

@vbp Ich brauche den oberen Rand für das erste Kind, den unteren Rand für das andere Kind. Wie könnte ich erreichen. Es ist etwas ähnliches wie id.first Kind in CSS
Prabs

@ Prabs erwägen die Verwendung eines Fragments, einer Recycling-Ansicht oder einer benutzerdefinierten Ansicht anstelle von NavigationView zur besseren Anpassung
vbp

1
Ich habe navMenuView.addItemDecoration(new DividerItemDecoration(NavigationViewActivity.this, DividerItemDecoration.VERTICAL));für perfekte Artikel Grenze getan
Prabs

19

Einfach DeviderItemDecoration hinzufügen:

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

Es sieht so aus:

Geben Sie hier die Bildbeschreibung ein


Kann ich die addItemDecorationZeilenhöhe auf 1px ändern?
Prabs

Vielen Dank, dass Ihre Lösung für mich funktioniert hat. Ich schätze. Bro noch eine Frage dazu. Ist es möglich, den oberen Rand für das erste Element zu entfernen und Rahmen nur für den unteren Rand der Elemente festzulegen?
Viper

@ Viper bitte beziehen Sie sich auf diese: bignerdranch.com/blog/…
SANAT

1
Diese Art von Teiler für jeden Gegenstand folgt nicht Material Guyidelines
Boris Ruzanov

19

Sie können Teiler einfach hinzufügen, indem Sie den Menüelementhintergrund über XML mithilfe von festlegen 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"/>

Und verwenden Sie LayerDrawable als Hintergrund. Es bewahrt die Welligkeit der Materialdesign-Überlagerung für Klicks.

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

Das Ergebnis:

Geben Sie hier die Bildbeschreibung ein


2
scheint die beste Antwort zu sein und keine Gruppe beteiligt
Michał Ziobro

Was ist, wenn Sie eine benutzerdefinierte Hintergrundfarbe für das ausgewählte Element verwenden möchten?
Ataravati

Ich habe einen Fehler bei <shape>: Element ist hier nicht erlaubt
Sébastien REMY

11

Ich denke, ich habe eine noch bessere Lösung für das Problem mehrerer geprüfter Elemente. Auf meine Weise müssen Sie sich keine Gedanken über das Ändern Ihres Codes machen, wenn Sie Ihrem Menü neue Abschnitte hinzufügen. Mein Menü sieht genauso aus wie die von Jared geschriebene akzeptierte Lösung, mit dem Unterschied, dass andoid verwendet wird: checkableBehavior = " all " für die Gruppen:

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

Das checkableBehavior von 'all' ermöglicht es, einzelne Elemente nach Belieben zu aktivieren / deaktivieren, unabhängig davon, zu welcher Gruppe sie gehören. Sie müssen nur das zuletzt überprüfte Menü speichern. Der Java-Code sieht folgendermaßen aus:

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

Wenn Sie verschiedene Gruppen wie Nileshs Antwort erstellen, wird zwar eine Trennlinie dazwischen erstellt, es entsteht jedoch das Problem, dass zwei markierte Elemente in der Navigationsleiste angezeigt werden.

Ein einfacher Weg, wie ich damit umgegangen bin, war:

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

Noch einfacher:android:checkableBehavior="none"
Espinchi

2
@espinchi - Das funktioniert nicht, wenn andere Gruppen Navigationsmenüelemente enthalten. Diese Lösung kann nur für Aktionen verwendet werden. Nicht gute UX-Praxis
Mushtaq Jameel

Ausgezeichnet! Es ist möglicherweise klarer, wenn Sie Ihre undefinierten Konstanten NAV_ITEMS_MAIN und NAV_ITEMS_EXTRA mit R.id.nav_items_group_main oder R.id.nav_items_group_extra ändern und Ihrem Beispiel das erforderliche XML hinzufügen
ChrisPrime

IS onNavigationItemSelected (endgültiges MenuItem menuItem) {Standardmethode ?? Wo soll ich diesen Code machen?
John

und was ist NAV_ITEMS_MAIN?
John

8

Ich bin mir nicht sicher, ob dies behoben ist API 26 (Android 8)oder ob es die ganze Zeit möglich war. Ich bin immer noch ein Neuling in der Android-Programmierung. Ich habe jedoch die folgenden Elterngruppen hinzugefügt. Testen auf einem physischen Android 6-Telefon,

  1. Ich habe den Teiler
  2. Wenn Sie ein Element aus einem auswählen nav_g1oder nav_g2die Auswahl anderer Elemente aufheben.
  3. Keine zusätzliche Auffüllung aufgrund verschachtelter Gruppen hinzugefügt.
  4. Ich habe Javaden Hörern keinen Code hinzugefügt

Menücode

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

Anmerkungen

  1. Wie in dieser Antwort erwähnt, muss jede Gruppe eine eindeutige ID haben, um den Teiler anzuzeigen.
  2. Gemäß dieser Antwort stimmen die Leerzeichen mit den Google-Materialdesignspezifikationen überein.
  3. Das Vorhandensein android:checkableBehavior="single"einer übergeordneten Gruppe ist erforderlich, damit das Problem mehrerer ausgewählter Menüelemente in dieser Antwort (in den Kommentaren von hungrigem Host erwähnt) nicht auftritt

Und hier ist der Screenshot

Screenshot des Gerätebildschirms


5

Ich wollte Trennwände über dem ersten und nach dem letzten Artikel. Mit der @ Nilesh-Lösung musste ich Dummy-Menüelemente hinzufügen und auf false setzen, was sich wirklich schmutzig anfühlte. Und was ist, wenn ich andere coole Sachen in meinem Menü machen möchte?

Mir ist aufgefallen, dass NavigationView FrameLayout erweitert, sodass Sie Ihre eigenen Inhalte wie bei einem FrameLayout darin einfügen können. Ich habe dann eine leere Menü-XML festgelegt, sodass nur mein benutzerdefiniertes Layout angezeigt wird. Ich verstehe, dass dies wahrscheinlich gegen den Weg verstößt, den Google von uns erwartet, aber wenn Sie ein wirklich benutzerdefiniertes Menü wünschen, ist dies eine einfache Möglichkeit, dies zu tun.

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

Hier ist der Stil

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

Und zeichnbar

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

Und das Menü

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

bearbeiten:

Anstelle von Schaltflächen können Sie TextView mit Drawable verwenden, das das Aussehen der ursprünglichen Menüelemente nachahmt:

 <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
Vielen Dank, anscheinend die bequemste Art, benutzerdefinierte Ansichten als Menüelemente zu haben
Jan Rabe

Ich benutze diese Lösung auch, weil es mir einfacher macht, die benutzerdefinierte Schriftart von Elementen
festzulegen

1

Das Guthaben sollte für die Lösung an Zorawar gehen. Entschuldigung für das Duplizieren der Antwort, aber es konnte nicht so viel formatierter Text in einen Kommentar eingefügt werden.

Die Lösung von Zorawar funktioniert, der Code könnte als solcher verbessert werden:

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

Was ist NAV_ITEMS_MAIN und NAV_ITEMS_EXTRA und Gruppen-ID?
John

Sie sind Konstanten für die group_id
Mushtaq Jameel

0

Nilehs Antwort ist richtig, außer dass es einen Fehler bei der doppelten Überprüfung gibt.

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

Also mit

android: checkableBehavior = "single"

mit eindeutiger ID soll das Problem lösen


0

Wenn Sie einen Teiler dynamisch hinzufügen möchten , können Sie einfach ein leeres Untermenü wie folgt hinzufügen:

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

Dadurch wird ein Teiler hinzugefügt.

Stellen Sie nur sicher, dass Sie bei der Verwendung den richtigen Index übergeben menu.getItem(int index)


0

Zusätzlich zu den vorherigen Antworten können Sie allen Gruppen dieselbe Gruppen-ID zuweisen, wenn Sie dekorative Trennzeichen möchten, aber aufgrund von Problemen mit "überprüfbarem Verhalten" nicht mehrere Gruppen erstellen möchten.

Beispiel:

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

Wenn die ausgewählte Antwort für Sie nicht funktioniert, können Sie versuchen, diese onCreateOptionsMenuzusätzlich hinzuzufügen , um die eindeutige Gruppen-ID zu erhalten:

if (Build.VERSION.SDK_INT >= 28) {
    menu.setGroupDividerEnabled(true)
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.