Làm cách nào để tạo một bộ chia đơn giản trong NavigationView mới?


153

Google đã giới thiệu NavigationViewtrong Thư viện hỗ trợ thiết kế phiên bản 22.2.0 mà bạn có thể tạo ngăn kéo rất dễ dàng bằng cách sử dụng tài nguyên menu.

Làm thế nào tôi có thể tạo một đường phân chia đơn giản giữa hai mục? Nhóm các mục không hoạt động. Tạo một phần mục con sẽ tạo một dòng chia, nhưng nó yêu cầu một tiêu đề, điều mà tôi không muốn.

Bất kỳ trợ giúp sẽ được đánh giá cao.


Như đã nêu trong các ý kiến ​​cho nó, vấn đề với câu trả lời được chấp nhận là, hành vi có thể kiểm tra không hoạt động trên nhiều nhóm (song song). Để tránh điều này, không tạo các nhóm song song, nhưng việc sử dụng phụ menu hoặc nhóm phụ để có được chia của bạn như được mô tả trong câu trả lời của tôi ở đây: stackoverflow.com/questions/30766919/...
Till

Câu trả lời:


319

Tất cả bạn cần làm là xác định một groupvới một ID duy nhất , tôi đã kiểm tra việc thực hiện nếu nhóm có id khác nhau của nó sẽ tạo ra một gốc cây.

Menu ví dụ, tạo dấu phân cách:

<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
Tự hỏi tại sao điều này (theo như tôi biết) không được ghi lại. Tôi nghĩ rằng nó sẽ được hỏi rất nhiều. Cảm ơn!
Gaëtan

16
Một vấn đề với cách tiếp cận này là setCheckeddường như hoạt động ở cấp độ nhóm. Nếu bạn chọn một mục trong Nhóm A, sau đó mở lại ngăn kéo và chọn mục trong Nhóm B, cả hai mục sẽ vẫn được tô sáng. Có thể Google sẽ khắc phục hành vi này trong phiên bản tiếp theo, nhưng hiện tại, đó là nhược điểm của việc sử dụng nhiều nhóm với NavigationView.
đói bụng

3
Tuyệt quá. Về kiểm tra kép, hãy thử android:checkableBehavior="none"cho nhóm thứ hai của bạn (đó là hành động, không phải điều hướng, tôi giả sử)
đặc biệt là

12
Điều thú vị là, nếu bạn xóa id khỏi groupnó, nó sẽ biên dịch và chạy nhưng các bộ chia bị ẩn đi.
Vahid Amiri

5
Điều này cũng không làm việc cho tôi. Tôi muốn các dòng giữa các nhóm menu, không phải sau mỗi mục.
Rich Morey

54

tạo một draw_item_bg.xml có thể vẽ như thế này,

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

và thêm nó vào NavigationView dưới dạng ứng dụng: itemBackground = "@ drawable / ngăn_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"/>

và ở đây chúng tôi đi ...nhập mô tả hình ảnh ở đây


1
Điều này hoạt động, nhưng nó cũng loại bỏ phần đệm bên trái của biểu tượng vật phẩm. ít nhất là trong mã của tôi, không phải trong ảnh chụp màn hình của bạn vì một số lý do
luky

@vbp Mình cần viền trên cho con đầu, viền dưới cho con khác. Làm thế nào tôi có thể đạt được. Nó là một cái gì đó tương tự như đứa trẻ đầu tiên trong css
Mitchs

@Prabs xem xét sử dụng phân đoạn, tái chế hoặc chế độ xem tùy chỉnh thay vì NavigationView để tùy chỉnh tốt hơn
vbp

1
Tôi đã làm navMenuView.addItemDecoration(new DividerItemDecoration(NavigationViewActivity.this, DividerItemDecoration.VERTICAL));cho biên giới item hoàn hảo
Prabs

19

Thêm đơn giản DeviderItemDecor:

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

Nó trông như thế này:

nhập mô tả hình ảnh ở đây


Tôi có thể thay đổi chiều cao của addItemDecorationdòng thành 1px không?
Mitchs

Cảm ơn bạn giải pháp của bạn đã làm việc cho tôi. Tôi đánh giá cao. Bro thêm một câu hỏi với điều này. Có thể loại bỏ đường viền trên cùng cho mục đầu tiên và chỉ đặt đường viền ở dưới cùng của mục không?
viper

@viper vui lòng tham khảo điều này: bignerdranch.com/blog/ Ấn
SANAT 15/03/2017

1
Loại chia này cho mỗi mục không tuân theo Nguyên tắc Vật chất
Boris Ruzanov

19

Bạn có thể dễ dàng thêm các bộ chia bằng cách đặt Nền Mục menu qua XML bằng cách sử dụng 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"/>

Và sử dụng LayerDrawable làm nền. Nó bảo tồn lớp phủ gợn sóng thiết kế vật liệu cho các nhấp chuột.

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

Kết quả:

nhập mô tả hình ảnh ở đây


2
dường như là câu trả lời hay nhất và không có nhóm nào tham gia
Michał Ziobro

Nếu bạn muốn sử dụng màu nền tùy chỉnh cho mục đã chọn thì sao?
ataravati

Tôi có lỗi trên <shape>: Phần tử không được phép ở đây
Sébastien REMY

11

Tôi nghĩ rằng tôi có một giải pháp thậm chí tốt hơn cho vấn đề của nhiều mục được kiểm tra. Sử dụng theo cách của tôi, bạn không phải lo lắng về việc thay đổi mã của mình khi thêm các phần mới vào menu. Menu của tôi trông giống như giải pháp được chấp nhận được viết bởi Jared, với sự khác biệt của việc sử dụng andoid: checkableBehavior = " all " trên các nhóm:

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

Tính năng có thể kiểm tra của 'tất cả' cho phép kiểm tra / bỏ chọn các mục đơn lẻ theo ý muốn, độc lập với nhóm chúng thuộc về nhóm nào. Bạn chỉ cần lưu trữ menuitem kiểm tra cuối cùng. Mã java trông như thế này:

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

Tạo các nhóm khác nhau như câu trả lời của Nilesh sẽ tạo ra một dải phân cách ở giữa Nhưng tạo ra vấn đề của hai mục được kiểm tra trong ngăn kéo điều hướng.

Một cách đơn giản để tôi xử lý việc này là:

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

Thậm chí đơn giản hơn:android:checkableBehavior="none"
Espinchi

2
@espinchi - Điều đó sẽ không hoạt động nếu các nhóm khác chứa các mục menu điều hướng. Giải pháp này chỉ có thể hoạt động cho các hành động. Thực hành UX không tốt
Mushtaq Jameel

Thông minh! Có thể rõ ràng hơn nếu bạn thay đổi các hằng số chưa xác định của mình NAV_ITEMS_MAIN và NAV_ITEMS_EXTRA với R.id.nav_items_group_main hoặc R.id.nav_items_group_extra và thêm XML cần thiết vào ví dụ của bạn
ChrisPrime

IS onNavlationItemSelected (menu MenuItem cuối cùngItem) {Phương thức mặc định ?? Tôi nên làm mã này ở đâu?
Giăng

và NAV_ITEMS_MAIN là gì ??
Giăng

8

Tôi không chắc chắn nếu điều này được cố định API 26 (Android 8)hoặc nó có thể mọi lúc. Tôi vẫn là một người mới trong lập trình Android. Tuy nhiên tôi đã thêm các nhóm phụ huynh như dưới đây. Thử nghiệm trên điện thoại vật lý Android 6,

  1. Tôi có dải phân cách
  2. Lựa chọn bất kỳ mục từ một trong hai nav_g1hoặcnav_g2 sẽ bỏ chọn các mục khác.
  3. Không có phần đệm thêm được thêm vào do các nhóm lồng nhau.
  4. Tôi đã không thêm bất kỳ Javamã nào cho người nghe

Mã thực đơn

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

Ghi chú

  1. Như đã đề cập trong này câu trả lời mỗi nhóm cần có một Id duy nhất để hiển thị dải phân cách.
  2. Theo này câu trả lời không gian được phù hợp với google thông số kỹ thuật thiết kế vật liệu.
  3. android:checkableBehavior="single"nhóm phụ huynh là bắt buộc, vì vậy vấn đề của nhiều mục menu được chọn trong câu trả lời này (được đề cập trong các bình luận của hungghost) không xảy ra

Và đây là ảnh chụp màn hình

Ảnh chụp màn hình của màn hình thiết bị


5

Tôi muốn chia trên mục đầu tiên và sau mục cuối cùng. Sử dụng giải pháp @Nilesh, tôi đã phải thêm các mục menu giả và đặt kích hoạt thành false mà cảm thấy thực sự bẩn. Cộng với những gì nếu tôi muốn làm những thứ tuyệt vời khác trong menu của tôi?

Tôi nhận thấy NavigationView mở rộng FrameLayout để bạn có thể đặt nội dung của riêng bạn vào đó giống như bạn làm cho FrameLayout. Sau đó tôi đặt một menu trống xml để nó chỉ hiển thị bố cục tùy chỉnh của tôi. Tôi hiểu rằng điều này có thể đi ngược lại con đường Google muốn chúng tôi thực hiện nhưng nếu bạn muốn có một menu thực sự tùy chỉnh thì đây là một cách dễ dàng để làm điều đó.

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

Đây là phong cách

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

Và có thể vẽ

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

Và thực đơn

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

biên tập:

Thay vì các Nút, bạn có thể sử dụng TextView với drawable để mô phỏng các mục menu ban đầu trông:

 <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
cảm ơn, rõ ràng là cách thuận tiện nhất để có chế độ xem tùy chỉnh dưới dạng các mục trong menu
Jan Rabe

tôi cũng sử dụng giải pháp này vì nó cho phép tôi dễ dàng thiết lập phông chữ tùy chỉnh của các mục và thay đổi màu của dải phân cách
luky

1

Tín dụng nên đến Zorawar để tìm giải pháp, Xin lỗi vì đã sao chép câu trả lời nhưng không thể thêm quá nhiều văn bản được định dạng trong một nhận xét.

Giải pháp của Zorawar hoạt động, mã có thể được cải thiện như sau:

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 và NAV_ITEMS_EXTRA và groupid là gì ??
Giăng

Họ là hằng số cho nhóm_id
Mushtaq Jameel

0

Câu trả lời của Nileh là đúng, ngoại trừ nó có một lỗi kiểm tra kép.

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

Vì vậy, sử dụng

android: checkableBehavior = "độc thân"

với id duy nhất sẽ giải quyết vấn đề


0

Nếu bạn muốn thêm dải phân cách động , bạn có thể chỉ cần thêm một SubMothy trống như thế này:

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

điều này sẽ thêm một dải phân cách.

chỉ cần chắc chắn để vượt qua đúng chỉ mục khi sử dụng menu.getItem(int index)


0

Ngoài các câu trả lời trước nếu bạn muốn phân tách trang trí nhưng không muốn tạo nhiều nhóm vì vấn đề "hành vi có thể kiểm tra" - bạn có thể gán cùng một id nhóm cho tất cả các nhóm của mình.

Thí dụ:

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

Nếu câu trả lời được chọn không phù hợp với bạn, bạn có thể muốn thử thêm câu này onCreateOptionsMenuvào để cung cấp id nhóm duy nhất:

if (Build.VERSION.SDK_INT >= 28) {
    menu.setGroupDividerEnabled(true)
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.