새로운 NavigationView에서 간단한 디바이더를 만드는 방법은 무엇입니까?


154

Google NavigationView은 메뉴 리소스를 사용하여 서랍을 매우 쉽게 만들 수있는 디자인 지원 라이브러리 버전 22.2.0을 도입했습니다 .

두 항목 사이에 간단한 구분선을 만들려면 어떻게해야합니까? 항목을 그룹화하지 못했습니다. 하위 항목 섹션을 만들면 구분선이 만들어 지지만 원하지 않는 제목이 필요합니다.

도움을 주시면 감사하겠습니다.


그것에 대한 의견에서 언급했듯이, 허용되는 대답의 문제는 확인 가능한 동작이 여러 (병렬) 그룹에서 작동하지 않는다는 것입니다. 이를 방지하려면, 병렬 그룹을 생성하지 않지만, 여기 내 대답에 설명 된대로 사용 하위 메뉴 또는 하위 그룹은 칸막이를 얻을 : stackoverflow.com/questions/30766919/...
까지

답변:


319

당신이해야 할 일은 고유 ID로를 정의하는 것 group입니다. 그룹이 다른 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
왜 이것이 내가 아는 한 문서화되지 않았는지 궁금합니다. 나는 그것이 많이 요구 될 것이라고 생각한다. 감사!
Gaëtan

16
이 방법의 한 가지 문제 setChecked는 그룹 수준에서 작동 하는 것 같습니다. 그룹 A에서 항목을 선택한 다음 서랍을 다시 열고 그룹 B에서 항목을 선택하면 두 항목이 모두 강조 표시됩니다. Google은 다음 릴리스에서이 동작을 수정했을 수도 있지만 현재 NavigationView에서 여러 그룹을 사용하면 단점이 있습니다.
hungryghost

3
큰. 이중 확인에 대해서는 두 android:checkableBehavior="none"번째 그룹 (탐색이 아닌 동작)을 시도 하십시오.
espinchi

12
재미있는 점은 ID에서 ID를 제거 group하면 컴파일되고 실행되지만 디바이더는 숨겨져 있다는 것입니다.
Vahid Amiri

5
이것은 나에게도 효과가 없다. 각 항목 다음이 아니라 메뉴 그룹 사이에 줄을 원했습니다.
Rich Morey 2016 년

54

이와 같이 drawable 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 자식과 유사합니다
Prabs

@Prabs 더 나은 사용자 정의에 대한 NavigationView 대신 조각, 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 February

당신의 솔루션이 나를 위해 일해 주셔서 감사합니다. 감사합니다. 이것에 대해 하나 더 질문하십시오. 첫 번째 항목의 위쪽 테두리를 제거하고 항목의 아래쪽에만 테두리를 설정할 수 있습니까?
viper

@ viper 참조하시기 바랍니다 : bignerdranch.com/blog/…
SANAT

1
각 품목에 대한 그러한 종류의 분배기는 Material Guyidelines를 따르지 않습니다
Boris Ruzanov

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>에 오류가 있습니다. 요소를 사용할 수 없습니다
Sébastien REMY

11

여러 개의 체크 된 항목의 문제에 대해 더 나은 해결책이 있다고 생각합니다. 내 방식을 사용하면 메뉴에 새 섹션을 추가 할 때 코드 변경에 대해 걱정할 필요가 없습니다. 내 메뉴는 그룹에서 andoid : checkableBehavior = " all "을 사용하는 것과는 달리 Jared가 작성한 허용 된 솔루션과 같습니다.

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

'all'의 checkableBehavior를 사용하면 그룹에 관계없이 단일 항목을 마음대로 확인 / 선택 취소 할 수 있습니다. 마지막으로 확인한 메뉴 항목 만 저장하면됩니다. 자바 코드는 다음과 같습니다.

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의 답변과 같은 다른 그룹을 만들면 사이에 구분이 이루어 지지만 탐색 창에서 두 개의 확인 된 항목의 문제가 발생합니다.

내가 이것을 처리하는 간단한 방법은 다음과 같습니다.

    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

우수한! 그것은 당신이 R.id.nav_items_group_main 또는 R.id.nav_items_group_extra로 정의되지 않은 상수 NAV_ITEMS_MAIN 및 NAV_ITEMS_EXTRA를 변경 한 경우 명확하고 예에 필요한 XML을 추가 할 수 있습니다
ChrisPrime

IS onNavigationItemSelected (최종 MenuItem menuItem) {기본 메소드 ?? 이 코드는 어디에서해야합니까?
John

NAV_ITEMS_MAIN은 무엇입니까 ??
John

8

이것이 고정되어 있는지 API 26 (Android 8)또는 항상 가능 했는지 확실하지 않습니다 . 나는 여전히 안드로이드 프로그래밍의 멍청한 놈이다. 그러나 아래와 같이 부모 그룹을 추가했습니다. 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. 대답 공간 구글 재료 설계 사양과 일치한다.
  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
감사합니다. 메뉴 항목으로 사용자 정의보기를 갖는 가장 편리한 방법
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

0

Nileh의 답변은 옳습니다. 단 하나의 이중 확인 결함이 있습니다.

<?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 = "단일"

고유 ID로 문제를 해결해야합니다.


0

분배기를 동적으로 추가하려면 다음과 같이 빈 하위 메뉴를 추가하면됩니다.

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.