Làm cách nào để tùy chỉnh nền mục và màu văn bản mục bên trong NavigationView?


Câu trả lời:


4

Với Thư viện MaterialComponents, bạn có thể sử dụng các thuộc tính sau:

  • app:itemShapeFillColor: màu nền của mục
  • app:itemIconTint: biểu tượng màu
  • app:itemTextColor: văn bản màu

Trong bố cục:

<com.google.android.material.navigation.NavigationView
    app:itemShapeFillColor="@color/shape_selector"
    app:itemIconTint="@color/icon_tint_selector"
    app:itemTextColor="@color/text_color_selector"
    ../>

Trong một phong cách tùy chỉnh:

<style name="..." parent="Widget.MaterialComponents.NavigationView" >
   <item name="itemShapeFillColor">@color/shape_selector</item>
   <item name="itemIconTint">@color/icon_tint_selector</item>
   <item name="itemTextColor">@color/text_color_selector</item>
</style>

Đối với itemIconTintitemTextColorbạn có thể sử dụng một bộ chọn như sau:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:color="?attr/colorPrimary" android:state_checked="true"/>
  <item android:alpha="0.38" android:color="?attr/colorOnSurface" android:state_enabled="false"/>
  <item android:color="?attr/colorOnSurface"/>
</selector>

Đối với itemShapeFillColorbạn, bạn có thể sử dụng một bộ chọn như:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:alpha="0.12" android:color="?attr/colorPrimary" android:state_activated="true"/>
  <item android:alpha="0.12" android:color="?attr/colorPrimary" android:state_checked="true"/>
  <item android:color="@android:color/transparent"/>
</selector>

Chỉ là một lưu ý cuối cùng . Hãy chú ý để sử dụng itemBackground.
Nó được thiết lập để @nullsử dụng nền định hình được tạo lập trình theo NavigationViewthời điểm itemShapeAppearancevà / hoặc itemShapeAppearanceOverlayđược đặt ( hành vi mặc định ).
Nền này được tạo kiểu bằng cách sử dụng các itemShape*thuộc tính.
Cài đặt itemBackgroundsẽ ghi đè nền có lập trình và khiến các giá trị được đặt trong thuộc tính itemShape * bị bỏ qua.

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


131

itemBackground, itemIconTintitemTextColorrất đơn giản xml-thuộc tính có thể được thiết lập, mặc dù bạn phải sử dụng một tiền tố tùy chỉnh thay vì android:một.

Thí dụ

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <!-- Other layout views -->

    <android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        app:itemBackground="@drawable/my_ripple"
        app:itemIconTint="#2196f3"
        app:itemTextColor="#009688"
        app:headerLayout="@layout/nav_header"
        app:menu="@menu/drawer_view" />

</android.support.v4.widget.DrawerLayout>

Lưu ý: Trong trường hợp này, màu văn bản, màu biểu tượng và nền là tĩnh. Nếu bạn muốn thay đổi màu của văn bản (ví dụ: màu hồng khi bỏ chọn và màu xanh lục khi được chọn), bạn nên sử dụng a ColorStateList.

Thí dụ

Tạo một tệp * .xml mới trong /res/color- đặt tên là state_list.xml - với nội dung sau:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- This is used when the Navigation Item is checked -->
    <item android:color="#009688" android:state_checked="true" />
    <!-- This is the default text color -->
    <item android:color="#E91E63" />
</selector>

và sau đó chỉ cần tham chiếu nó như thế này: app:itemTextColor="@color/state_list"

Cũng vậy itemIconTint. itemBackgroundmong đợi một id tài nguyên. Xem tài liệu là tốt.


1
đối với nền mục trong mục đã kiểm tra, chỉ cần sử dụng <item name = "colorControlHighlight"> # 123456 </item>
Xan

1
Điều đó đúng nhưng điều này cũng có thể thay đổi màu sắc của các chế độ xem khác EditTextít nhất là nếu bạn xác định nó trong Chủ đề chung của mình.
reVerse

3
Có ai gặp sự cố khi cài đặt app:itemBackground="@drawable/my_ripple"không? Điều xảy ra với tôi là khi tôi nhấn một mục, mục ở dưới cùng phản ánh hiệu ứng gợn sóng thay vì tôi thực sự đang nhấn.
Javier Mendonça

@JavierMendonca Tôi đã gặp phải trường hợp tương tự nhưng tôi không biết cách sửa lỗi cho atm này - rất có thể đây là một lỗi nhưng có lẽ bạn nên đặt một câu hỏi riêng cho vấn đề cụ thể này.
reVerse

3
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

97

NavigationDrawer (NavigationView) có ba tùy chọn để cấu hình các mục đã chọn / đã chọn.

app:itemIconTint="@color/menu_text_color" //icon color
app:itemTextColor="@color/menu_text_color" //text color
app:itemBackground="@drawable/menu_background_color" //background

Biểu tượng và màu văn bản

Hai tùy chọn đầu tiên (biểu tượng và văn bản) cần tài nguyên danh sách trạng thái màu - https://developer.android.com/guide/topics/resources/color-list-resource.html .

menu_text_colorTài nguyên như vậy cần được tạo bằng res / color . Nội dung tệp này sẽ trông giống như:

<!-- res/color/menu_text_color.xml -->
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:color="@color/colorWhite" android:state_checked="true" />
  <item android:color="@color/colorBlack" android:state_checked="false"/>
</selector>
  • @color/colorWhite - tài nguyên màu được sử dụng cho mục đã kiểm tra

  • @color/colorBlack - tài nguyên màu được sử dụng cho mục không được chọn

Tôi đã tạo một tài nguyên cho cả hai, nhưng có thể tạo hai tệp riêng biệt - một cho văn bản, một cho biểu tượng.

Nền (itemBackground)

Tùy chọn nền cần tài nguyên có thể vẽ thay vì màu, mọi cố gắng đặt màu sẽ kết thúc bởi ngoại lệ. Tài nguyên có thể vẽ cần được tạo ở dạng res / drawable và nội dung của nó phải tương tự như:

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

Không cần tạo bất kỳ bảng vẽ nào mô phỏng màu sắc (trong các giải pháp khác, tôi thấy các đề xuất như vậy - có thể cho phiên bản sdk cũ hơn), màu có thể được sử dụng trực tiếp trong tệp này. Trong tệp ví dụ này, tôi đang sử dụng màu trong suốt cho mục chưa kiểm tra và colorPrimarymục đã kiểm tra.

Khắc phục sự cố và ghi chú quan trọng

  • Trong tài nguyên nền luôn sử dụng state_checked = "false" thay vì mặc định, với màu mặc định, nó sẽ không hoạt động
  • Đối với menu được tạo động / lập trình, hãy nhớ đặt các mục là có thể kiểm tra :

Ví dụ về mã (thêm mục menu động):

  menu.add(group_id, item_id, Menu.NONE, item_name).setCheckable(true).setChecked(false);

Nếu các mục không được đặt là có thể kiểm tra thì nền sẽ không hoạt động (màu văn bản và biểu tượng đáng ngạc nhiên sẽ hoạt động như mong đợi).


1
câu trả lời tốt nhưng tôi thích tạo một chủ đề cho chế độ xem điều hướng. tôi cần ghi đè phần nào?
Xan

@MaciejSikora Bạn cứu mạng tôi! Tôi yêu các bạn! Cưới anh đi :)
Krzysiek

Đây là điều quan trọng nhất không có gì khác hoạt động. remember to set items as checkable. Cảm ơn bạn đã đề cập đến điều này, mà không ai đã làm.
SimpleGuy

8

Tôi sử dụng colorControlHighlight là một giải pháp tốt. Lưu ý rằng với thư viện hỗ trợ mới nhất, bạn có thể xác định chủ đề (không chỉ kiểu) cho mọi tiện ích con; ví dụ, bạn có thể xác định colorControlHighlight vào chủ đề NavigationView và điều này sẽ không được áp dụng cho phần còn lại của widget.


3
câu trả lời hoàn hảo nhưng tôi cần ghi đè bản đính kèm nào trong chủ đề NavigationView để kiểm soát nền, màu văn bản và màu biểu tượng?
Xan

vâng, chắc chắn rồi, hãy tạo một kiểu với <item name="android:colorControlHighlight">@color/navigationDrawerTextNight</item>nhưng nó được áp dụng như thế nào cho văn bản mục menu ?? itemTextColorkhông tồn tại trong một phong cách
Có người Somewhere

6

Nếu bạn chỉ muốn thay đổi một màu mục menu từ hoạt động của mình trong các sự kiện, hãy xem blog này của HANIHASHEMI:

https://hanihashemi.com/2017/05/06/change-text-color-of-menuitem-in-navigation-drawer/

private void setTextColorForMenuItem(MenuItem menuItem, @ColorRes int color) {
  SpannableString spanString = new SpannableString(menuItem.getTitle().toString());
  spanString.setSpan(new ForegroundColorSpan(ContextCompat.getColor(this, color)), 0, spanString.length(), 0);
  menuItem.setTitle(spanString);
}

Phương thức gọi

setTextColorForMenuItem(item, R.color.colorPrimary);

Nếu bạn làm việc với Xamarin Android, hãy thử cách này:

private void SetTextColorForMenuItem(IMenuItem menuItem, Android.Graphics.Color color)
        {
            SpannableString spanString = new SpannableString(menuItem.TitleFormatted.ToString());
            spanString.SetSpan(new ForegroundColorSpan(color), 0, spanString.Length(), 0);
            menuItem.SetTitle(spanString);
        }

Phương thức gọi:

SetTextColorForMenuItem(navigationView.Menu.GetItem(0), Android.Graphics.Color.OrangeRed);

5

Bạn có thể sử dụng mã này theo chương trình:

int[][] states = new int[][] {
    new int[] { android.R.attr.state_enabled}, // enabled
    new int[] {-android.R.attr.state_enabled}, // disabled
    new int[] {-android.R.attr.state_checked}, // unchecked
    new int[] { android.R.attr.state_pressed}  // pressed
};

int[] colors = new int[] {
    Color.BLACK,
    Color.RED,
    Color.GREEN,
    Color.BLUE
};

ColorStateList myList = new ColorStateList(states, colors);

  nav_view.setItemIconTintList(myList);

3

Bây giờ, trong chế độ xem điều hướng, bạn cũng có thể cung cấp chế độ xem mục của riêng mình. Với cái mới, appcompat-v7:23.1.0bạn có thể

đặt chế độ xem tùy chỉnh cho các mục thông qua ứng dụng: actionLayout hoặc sử dụng MenuItemCompat.setActionView ().

View view = View.inflate(context, R.layout.your_custom_nav_layout_item, null);
MenuItemCompat.setActionView(menuItem, view); 

Bằng cách này, bạn có thể tạo bố cục của riêng mình với TextView và thay đổi theo cách backgrounds/colors/fontsbạn muốn. Hy vọng điều này hữu ích :) Nguồn


0

Nếu bạn muốn làm điều này theo chương trình:

Dựa trên câu trả lời của Jhon:

Bạn có thể sử dụng tiện ích mở rộng Kotlin như sau:

fun NavigationView.setTextColorForMenuItems(@ColorInt color: Int) {
    for (i: Int in 0 until menu.size()) {
        val menuItem = menu.getItem(i)
        val spanString = SpannableString(menuItem.title.toString())
        spanString.setSpan(ForegroundColorSpan(color), 0, spanString.length, 0)
        menuItem.title = spanString
    }
}

Sau đó gọi

nav_view.setTextColorForMenuItems(Color.BLACK)

-1

Bạn có thể làm điều đó bằng cách sử dụng câu lệnh sau:

navigationView.setItemBackground(ContextCompat.getDrawable(CustomerHomeActivity.this, R.color.transparent));
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.