新しいNavigationViewでシンプルなディバイダーを作成する方法は?


154

Google NavigationViewはDesign Support Libraryバージョン22.2.0でを導入しました。これを使用すると、メニューリソースを使用して非常に簡単に引き出しを作成できます。

2つのアイテムの間に単純な分割線を作成するにはどうすればよいですか?アイテムのグループ化が機能しませんでした。サブアイテムセクションを作成すると区切り線が作成されますが、タイトルが必要ですが、これは不要です。

任意の助けいただければ幸いです。


それにコメントで述べたように、受け入れられた答えの問題は、チェック可能な動作が複数の(並列の)グループ間で機能しないことです。これを避けるために、並列グループを作成していないが、ここで私の答えで説明したように使用するサブメニューまたはサブグループは、あなたの分周器を得るために:stackoverflow.com/questions/30766919/...
ティル

回答:


319

必要なのはgroup一意のIDを使用してを定義することだけです。グループに異なる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>

9
なぜこれが(私の知る限り)文書化されていないのか疑問に思います。よく聞かれると思います。ありがとう!
ガエタン

16
このアプローチの1つの問題setCheckedは、グループレベルで機能するように見えることです。グループAのアイテムを選択してから、もう一度ドロワーを開いてグループBのアイテムを選択すると、両方のアイテムが強調表示されたままになります。たぶん、Googleは次のリリースでこの動作を修正するかもしれませんが、現時点では、NavigationViewで複数のグループを使用することの欠点です。
hungryghost

3
すごい。二重チェックについて、android:checkableBehavior="none"2番目のグループ(ナビゲーションではなくアクション)を試してください
espinchi

12
おかしいことに、IDを削除すると、groupコンパイルされて実行されますが、仕切りが非表示になります。
Vahid Amiri、2016

5
これも私にはうまくいきません。各アイテムの後にではなく、メニューグループの間に線が必要でした。
Rich Morey

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>

それをapp:itemBackground = "@ drawable / drawer_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"/>

さあ、いくぞ...ここに画像の説明を入力してください


1
これは機能しますが、アイテムアイコンの左側のパディングも削除されます。少なくとも私のコードでは、何らかの理由でスクリーンショットではありません
luky

@vbp最初の子には上枠、他の子には下枠が必要です。どうすれば達成できますか。これはcssのid.first childに似ています
Prabs

@Prabsは、NavigationViewではなく、fragment、recyclerview、またはカスタムビューの使用を検討して、カスタマイズを向上させます
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 に変更できますか?
Prabs 2017

あなたの解決策が私のために働いてくれてありがとう。ありがたいです。これでもう1つ質問をします。最初のアイテムの上部の境界線を削除して、アイテムの下部にのみ境界線を設定することは可能ですか?
viper

:@viperこのご参照くださいbignerdranch.com/blog/...
Sanatの

1
各アイテムのそのような仕切りは、マテリアルガイドラインに従っていません
ボリスルザノフ'26

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

そして、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>

結果:

ここに画像の説明を入力してください


2
最良の答えと関係していないグループのようだ
のMichałZiobro

選択したアイテムにカスタムの背景色を使用したい場合はどうなりますか?
ataravati

<shape>にエラーがあります:要素はここでは許可されていません
セバスチャンREMY

11

複数のチェックされたアイテムの問題に対するさらに良い解決策があると思います。私の方法を使用すると、メニューに新しいセクションを追加するときにコードを変更することを心配する必要はありません。私のメニューはJaredが作成した承認済みのソリューションと同じように見えますが、グループで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を使用すると、単一のアイテムが属するグループに関係なく、自由にチェック/チェック解除できます。最後にチェックしたメニューアイテムを保存するだけです。java-codeは次のようになります。

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

Nileshの回答のように異なるグループを作成すると、その間に仕切りができますが、ナビゲーションドロワーで2つのチェックされた項目の問題が発生します。

これを処理する簡単な方法は次のとおりです。

    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 2015

2
@espinchi-他のグループにナビゲーションメニュー項目が含まれている場合は機能しません。このソリューションは、アクションに対してのみ機能します。優れたUXプラクティス
Mushtaq Jameel、2015

優れた!R.id.nav_items_group_mainまたはR.id.nav_items_group_extraを使用して未定義の定数NAV_ITEMS_MAINおよびNAV_ITEMS_EXTRAを変更し、必要なXMLを例に追加すると、より明確になる場合があります
ChrisPrime

IS onNavigationItemSelected(final MenuItem menuItem){デフォルトのメソッド?? このコードはどこで実行すればよいですか?
John

NAV_ITEMS_MAINとは何ですか?
John

8

これが修正されたの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. これで述べたように回答で各グループには、分周器を示す一意のIDが必要です。
  2. あたりとして、この答えのスペースがGoogleの材料設計仕様に合致しています。
  3. 持つandroid:checkableBehavior="single"親グループのためで選択した複数のメニュー項目の問題よう要求され、この(hungryghostのコメントで述べた)答えは発生しません。

そして、これがスクリーンショットです

デバイス画面のスクリーンショット


5

最初のアイテムの上と最後のアイテムの後にディバイダーが欲しかった。@Nileshソリューションを使用して、ダミーのメニューアイテムを追加し、enabledを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
おかげで、明らかにカスタムビューをメニュー項目として持つ最も便利な方法
Jan Rabe

私はそれが私より容易な設定項目のカスタムフォントをすることができますので、また、このソリューションを使用し、分圧器の色変更
luky

1

クレジットは解決策として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);
}

NAV_ITEMS_MAINおよびNAV_ITEMS_EXTRAおよびgroupidとは何ですか?
John

これらはgroup_idの定数です
Mushtaq Jameel '25

0

ニレの答えは正しいですが、二重チェックの欠点が1つあります。

<?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 = "single"

一意のIDで問題を解決する


0

動的にディバイダーを追加したい場合は、次のように空のSubMenuを追加するだけです。

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

これは分周器を追加します。

使用するときは、正しいインデックスを渡してください。 menu.getItem(int index)


0

装飾的なセパレータが必要だが、「チェック可能な動作」の問題のために複数のグループを作成したくない場合は、以前の回答に加えて、すべてのグループに同じグループ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>


0

選択した回答がうまくいかない場合はonCreateOptionsMenu、一意のグループIDを追加するだけでなく、これに追加してみてください。

if (Build.VERSION.SDK_INT >= 28) {
    menu.setGroupDividerEnabled(true)
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.