Thay đổi màu của một mục menu đã chọn trong ngăn điều hướng


103

Tôi đang sử dụng thư viện Hỗ trợ thiết kế Android mới để triển khai ngăn điều hướng trong ứng dụng của mình.

Tôi không thể tìm ra cách thay đổi màu của một mục đã chọn!

Đây là xml của menu:

<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="single">
    <item
        android:id="@+id/navigation_item_1"
        android:icon="@drawable/ic_1"
        android:title="@string/navigation_item_1"/>

    <item
        android:id="@+id/navigation_item_2"
        android:icon="@drawable/ic_2"
        android:title="@string/navigation_item_2"/>
</group>

Và đây là chế độ xem điều hướng xml được đặt bên trong android.support.v4.widget.DrawerLayout:

<android.support.design.widget.NavigationView
    android:id="@+id/activity_main_navigationview"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    app:headerLayout="@layout/drawer_header"
    app:itemIconTint="@color/black"
    app:itemTextColor="@color/primary_text"
    app:menu="@menu/menu_drawer">

    <TextView
        android:id="@+id/main_activity_version"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:layout_marginBottom="@dimen/activity_vertical_margin"
        android:layout_marginLeft="@dimen/activity_horizontal_margin"
        android:textColor="@color/primary_text" />

</android.support.design.widget.NavigationView>

Cảm ơn sự giúp đỡ của bạn !

[EDIT] Tôi đã xem xét các giải pháp, chẳng hạn như giải pháp này: Thay đổi màu nền của menu android .

Nó có vẻ là một hack và tôi nghĩ rằng với Thư viện hỗ trợ thiết kế mới, một cái gì đó sạch hơn sẽ được giới thiệu?


có thể trùng lặp của Thay đổi màu nền của menu android
jlopez

Câu trả lời:


244

Bạn có thể đạt được điều này bằng cách sử dụng Tài nguyên trạng thái màu . Nếu bạn nhận thấy bên trong NavigationViewbạn đang sử dụng

app:itemIconTint="@color/black"
app:itemTextColor="@color/primary_text"

Ở đây thay vì sử dụng @color/blackhoặc @color/primary_test, hãy sử dụng a Color State List Resource. Để làm được điều đó, trước tiên hãy tạo một thư mục xmlbên trong mới (ví dụ: draw_item.xml) color(thư mục này phải nằm trong resthư mục bên trong .) Nếu bạn chưa có tên thư mục color, hãy tạo một thư mục.

Bây giờ bên trong drawer_item.xmllàm một cái gì đó như thế này

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="checked state color" android:state_checked="true" />
    <item android:color="your default color" />
</selector>

Bước cuối cùng sẽ là thay đổi NavigationView

<android.support.design.widget.NavigationView
    android:id="@+id/activity_main_navigationview"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    app:headerLayout="@layout/drawer_header"
    app:itemIconTint="@color/drawer_item"  // notice here
    app:itemTextColor="@color/drawer_item" // and here
    app:itemBackground="@android:color/transparent"// and here for setting the background color to tranparent
    app:menu="@menu/menu_drawer">

Như vậy, bạn có thể sử dụng riêng biệt Màu Danh sách nhà nước Tài nguyên cho IconTint, ItemTextColor, ItemBackground.

Bây giờ khi bạn đặt một mục là đã chọn (trong xmlhoặc theo chương trình), mục cụ thể sẽ có màu khác với những mục chưa được chọn.


Hãy nhớ rằng để nhấn hoạt động, bạn cần thay đổi nó từ android: state_checked thành android: state_pressed.
Programista

32
đối với ItemBackground, bạn cần sử dụng có thể vẽ thay vì màu vì bạn không thể xác định nền bằng tài nguyên màu.
sirFunkenstine

@sash nếu chúng ta muốn thực hiện thay đổi hình ảnh biểu tượng trên một mục điều hướng đã chọn thì chúng ta sẽ thực hiện điều này như thế nào?
mohit

@sirFunkenstine Nếu bạn đang sử dụng bộ chọn màu thì bạn có thể đặt nó vào thư mục màu trong thư mục res của mình.
Kishan Vaghela

@KishanVaghela làm những gì bạn cho thấy sản xuất lỗi này: Binary file XML dòng # 3: <item> thẻ đòi hỏi một 'drawable' thuộc tính hoặc con thẻ xác định một drawable
iOSAndroidWindowsMobileAppsDev

66

Tôi tin rằng app:itemBackgroundsẽ có một trận hòa. Vì vậy, hãy làm theo các bước dưới đây:

Tạo một tệp highlight_color.xmlcó thể vẽ được với các nội dung sau:

<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
     <solid android:color="YOUR HIGHLIGHT COLOR"/>
</shape>

Tạo một tệp nav_item_drawable.xmlcó thể vẽ khác với nội dung sau:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:drawable="@drawable/highlight_color" android:state_checked="true"/>
</selector>

Cuối cùng thêm app:itemBackgroundthẻ vào NavView:

<android.support.design.widget.NavigationView
android:id="@+id/activity_main_navigationview"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="@layout/drawer_header"
app:itemIconTint="@color/black"
app:itemTextColor="@color/primary_text"
app:itemBackground="@drawable/nav_item_drawable"
app:menu="@menu/menu_drawer">

ở đây tệp highlight_color.xml xác định một màu đồng nhất có thể vẽ được cho nền. Sau đó, màu có thể vẽ này được gán cho bộ chọn nav_item_drawable.xml.

Điều này đã làm việc cho tôi. Hy vọng rằng điều này sẽ giúp ích.

********************************************** ĐÃ CẬP NHẬT *** *******************************************

Mặc dù câu trả lời được đề cập ở trên cung cấp cho bạn khả năng kiểm soát tốt đối với một số thuộc tính, nhưng cách tôi sắp mô tả có cảm giác RẮN hơn và MÁT hơn một chút .

Vì vậy, những gì bạn có thể làm là, bạn có thể xác định một ThemeOverlay trong styles.xmlcho NavigationView như sau:

    <style name="ThemeOverlay.AppCompat.navTheme">

        <!-- Color of text and icon when SELECTED -->
        <item name="colorPrimary">@color/color_of_your_choice</item> 

        <!-- Background color when SELECTED -->
        <item name="colorControlHighlight">@color/color_of_your_choice</item> 

    </style>

bây giờ áp dụng ThemeOverlay này cho app:themethuộc tính của NavigationView, như sau:

<android.support.design.widget.NavigationView
android:id="@+id/activity_main_navigationview"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:theme="@style/ThemeOverlay.AppCompat.navTheme"
app:headerLayout="@layout/drawer_header"
app:menu="@menu/menu_drawer">

Hy vọng điều này có thể giúp cho bạn.


1
Ngoài ra, phương pháp này có thể được sử dụng như android:background="@drawable/nav_item_drawable"cho các widget khác như RadioButton, Checkbox, Button, v.v. Giảm lập trình bloatware để xử lý setOnCheckedChangeListenerchỉ để tô màu.
rupinderjeet

@Ankush này hoạt động nhưng văn bản và biểu tượng biến mất, tôi cũng đã đặt màu sắc cho mục nhưng nó không hoạt động. bạn có thể vui lòng gợi ý cho tôi cách nó có thể được thực hiện không
Người dùng

1
@User Tôi không biết điều gì đã xảy ra với mã của bạn, nhưng tôi đã thêm vào câu trả lời. Một cách hoàn toàn khác để đạt được điều tương tự với ít nỗ lực hơn. Bạn có thể kiểm tra điều đó.
Ankush

1
Đây nên được chấp nhận như một câu trả lời! Cảm ơn bạn rất nhiều, rất hữu ích !!!
Svetlana Rozhkova

4

Một người cần đặt NavigateItemkiểm tra true bất cứ khi nào mục trong NavigateViewđược nhấp vào

//listen for navigation events
NavigationView navigationView = (NavigationView)findViewById(R.id.navigation);
navigationView.setNavigationItemSelectedListener(this);
// select the correct nav menu item
navigationView.getMenu().findItem(mNavItemId).setChecked(true);

Thêm NavigationItemSelectedListenervàoNavigationView

  @Override
  public boolean onNavigationItemSelected(final MenuItem menuItem) {
    // update highlighted item in the navigation menu
    menuItem.setChecked(true);
    mNavItemId = menuItem.getItemId();

    // allow some time after closing the drawer before performing real navigation
    // so the user can see what is happening
    mDrawerLayout.closeDrawer(GravityCompat.START);
    mDrawerActionHandler.postDelayed(new Runnable() {
      @Override
      public void run() {
        navigate(menuItem.getItemId());
      }
    }, DRAWER_CLOSE_DELAY_MS);
    return true;
  }

Cảm ơn sự giúp đỡ của bạn Vikalp, nhưng tôi đã làm điều đó ( setChecked(true)). Tôi có thể thấy màu của mục đã chọn thay đổi nhưng tôi không thể tự sửa đổi, màu luôn là phiên bản sáng hơn của nền điều hướng.
Greg

@ Greg Theo mặc định setChecked(true)trên Viewmàu thay đổi nền tối đa chủ đề mà thiết bị bạn sử dụng. Nếu bạn thay đổi nền của mục thành một số màu khác thì bạn cần phải tăng bố cục của mình lên DrawerLayouthoặc NavigationViewvà tự xử lý.
Vikalp Patel

Cảm ơn một lần nữa, tôi đã cố gắng làm những gì bạn nói với tôi nhưng không thành công, bạn có một liên kết giải thích làm thế nào xin vui lòng?
Greg

2

Đây là một cách khác để đạt được điều này:

public boolean onOptionsItemSelected(MenuItem item) {

    int id = item.getItemId();

    item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
        @Override
        public boolean onMenuItemClick(MenuItem item) {
            item.setEnabled(true);
            item.setTitle(Html.fromHtml("<font color='#ff3824'>Settings</font>"));
            return false;
            }
        });


    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}

}


Dobut của tôi là về những gì nếu tôi muốn thay đổi màu sắc của mục đã chọn của menu bật lên, nhưng nhờ bạn mà tôi có một ý tưởng tuyệt vời từ giải pháp này của bạn để thay đổi màu của mục menu đã chọn ... vì vậy hãy cho bạn phiếu bầu !!! Và công việc xung quanh là :: item.setTitle (Html.fromHtml ("<font color = '# ff3824'> Cài đặt </font>"));
Tarit Ray

1

Đây là cách bạn có thể làm điều đó trong phương thức onCreate của Activity:

NavigationView navigationView = findViewById(R.id.nav_view);
ColorStateList csl = new ColorStateList(
    new int[][] {
        new int[] {-android.R.attr.state_checked}, // unchecked
        new int[] { android.R.attr.state_checked}  // checked
    },
    new int[] {
        Color.BLACK,
        Color.RED
    }
);
navigationView.setItemTextColor(csl);
navigationView.setItemIconTintList(csl);

1

Bước 1: Tạo bộ chọn đã chọn / đã chọn:

selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@color/yellow" android:state_checked="true" />
    <item android:color="@color/white" android:state_checked="false" />
</selector>

Bước 2: Sử dụng thuộc tính xml app:itemTextColortrong NavigationViewwidget để chọn màu văn bản.

<android.support.design.widget.NavigationView
    android:id="@+id/nav_view"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    app:headerLayout="@layout/navigation_header_layout"
    app:itemTextColor="@drawable/selector"
    app:menu="@menu/navigation_menu" />

Bước 3:
Vì một số lý do khi bạn nhấn một mục từ NavigationViewmenu, nó không coi đây là nút kiểm tra. Vì vậy, bạn cần phải kiểm tra mục đã chọn theo cách thủ công và xóa mục đã chọn trước đó. Sử dụng trình nghe bên dưới để làm điều đó

@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {

    int id = item.getItemId();

    // remove all colors of the items to the `unchecked` state of the selector
    removeColor(mNavigationView);

    // check the selected item to change its color set by the `checked` state of the selector
    item.setChecked(true);

    switch (item.getItemId()) {
      case R.id.dashboard:
          ...
    }

    drawerLayout.closeDrawer(GravityCompat.START);
    return true;
}

private void removeColor(NavigationView view) {
    for (int i = 0; i < view.getMenu().size(); i++) {
        MenuItem item = view.getMenu().getItem(i);
        item.setChecked(false);
    }
}

Bước 4:
Để thay đổi màu biểu tượng, hãy sử dụng app:iconTintthuộc tính trong các NavigationViewmục menu và đặt thành cùng một bộ chọn.

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/nav_account"
        android:checked="true"
        android:icon="@drawable/ic_person_black_24dp"
        android:title="My Account"
        app:iconTint="@drawable/selector" />
    <item
        android:id="@+id/nav_settings"
        android:icon="@drawable/ic_settings_black_24dp"
        android:title="Settings"
        app:iconTint="@drawable/selector" />

    <item
        android:id="@+id/nav_logout"
        android:icon="@drawable/logout"
        android:title="Log Out"
        app:iconTint="@drawable/selector" />
</menu>

Kết quả:

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.