Як налаштувати фон елемента та колір тексту елемента всередині NavigationView?


76

Я хочу досягти чогось подібного, показаного в Документах з матеріального дизайну .

colorControlHighlight використовується для фону на позначених елементах.

Мені потрібно налаштувати:

  • фон не позначено
  • перевірено колір тексту
  • колір тексту не позначений

Відповіді:


4

За допомогою бібліотеки MaterialComponents ви можете використовувати такі атрибути:

  • app:itemShapeFillColor: колір елемента тла
  • app:itemIconTint: відтінок значків
  • app:itemTextColor: колір тексту

У макеті:

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

У власному стилі:

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

Для itemIconTintі itemTextColorви можете використовувати селектор, такий як:

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

Для цього itemShapeFillColorви можете використовувати селектор, такий як:

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

Лише остання примітка . Зверніть увагу на використання itemBackground.
Встановлено значення для @nullвикористання фігурного фону, програмно сформованого, NavigationViewколи itemShapeAppearanceта / або itemShapeAppearanceOverlayвстановлено ( поведінка за замовчуванням ).
Цей фон оформлений за допомогою itemShape*атрибутів.
Параметр itemBackgroundперезапише програмний фон і призведе до ігнорування значень, встановлених в атрибутах itemShape *.

введіть тут опис зображення


131

itemBackground, itemIconTintі itemTextColorце прості атрибути xml, які можна встановити, хоча вам доведеться використовувати власний префікс замість android:одного.

Приклад

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

Примітка: У цьому випадку колір тексту, відтінок піктограм та фон є статичними. Якщо ви хочете змінити колір тексту (наприклад, рожевий, якщо не встановлено прапорець, і чирок, якщо позначений), вам слід використовувати a ColorStateList.

Приклад

Створіть новий файл * .xml у /res/color- назвемо його state_list.xml - із таким вмістом:

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

а потім просто посилайтеся на нього так: app:itemTextColor="@color/state_list"

Те саме стосується itemIconTint. itemBackgroundочікує ідентифікатор ресурсу. Дивіться також документи .


1
для фону елемента у позначеному елементі просто використовуйте <item name = "colorControlHighlight"> # 123456 </item>
Xan

1
Це правда, але це також може змінити колір інших поглядів, як EditTextмінімум, якщо ви визначите його у своїй глобальній темі.
reverse

3
У когось виникають проблеми при налаштуванні app:itemBackground="@drawable/my_ripple"? У мене трапляється, що коли я натискаю на елемент, той, що знаходиться в самому низу, відображає ефект пульсації замість того, який я насправді натискаю.
Хав'єр Мендонса

@JavierMendonca Я пережив те саме, але я не знаю виправлення для цього банкомату - швидше за все, це помилка, але, можливо, варто задати окреме запитання щодо цієї конкретної проблеми.
реверс

3
Пам'ятайте, що для натискання на роботу вам потрібно змінити його з android: state_ selected на android: state_pressed.
Programista

97

NavigationDrawer (NavigationView) має три варіанти конфігурації позначених / вибраних елементів.

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

Значок і колір тексту

Перші два варіанти (піктограма та текст) потребують ресурсу списку кольорів - https://developer.android.com/guide/topics/resources/color-list-resource.html .

Такий menu_text_colorресурс потрібно створити у кольорі res / color . Цей вміст файлу повинен виглядати приблизно так:

<!-- 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 - кольоровий ресурс, що використовується для позначеного елемента

  • @color/colorBlack - кольоровий ресурс, що використовується для непозначеного елемента

Я створив один ресурс для обох, але можна створити два окремі файли - один для тексту, один для значка.

Фон (itemBackground)

Для фонового варіанту потрібен ресурс, який можна малювати замість кольору, кожна спроба встановити колір закінчується виключенням. Ресурс, який можна малювати, потрібно створити в res / drawable, а його вміст повинен виглядати приблизно так:

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

Немає необхідності створювати будь-які малюнки, що імітують колір (в інших рішеннях я бачив такі пропозиції - можливо, для старшої версії sdk), колір можна використовувати безпосередньо у цьому файлі. У цьому прикладі файлу я використовую прозорий колір для неперевіреного елемента та colorPrimaryдля позначеного елемента.

Усунення несправностей та важливі примітки

  • У фоновому ресурсі завжди використовуйте state_ checked = "false" замість типового, із кольором за замовчуванням це не буде працювати
  • Для динамічного / програмно створеного меню не забудьте встановити пункти як перевіряються :

Приклад коду (додавання динамічного пункту меню):

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

Якщо елементи не будуть встановлені як перевіряються, тоді фон не працюватиме (дивовижний колір тексту та піктограм працюватиме, як очікувалося).


1
хороша відповідь, але я вважаю за краще створити тему для навігаційного перегляду. який attr мені потрібно замінити?
Xan

@MaciejSikora Ти врятуєш моє життя! Я люблю вас, чоловіки!
Виходь за

Це найголовніше, інакше нічого не працює. remember to set items as checkable. Дякую, що згадали про це, чого ніхто не робив.
SimpleGuy

8

Використання colorControlHighlight є хорошим рішенням для мене. Майте на увазі, що за допомогою останньої бібліотеки підтримки ви можете визначити тему (а не лише стиль) для кожного віджета; наприклад, ви можете визначити colorControlHighlight у темі NavigationView, і це не застосовуватиметься до решти віджетів.


3
ідеальна відповідь, але який атрибут мені потрібно замінити в темі NavigationView, щоб керувати фоном, кольором тексту та кольором значків?
Xan

так, звичайно, створіть стиль за допомогою, <item name="android:colorControlHighlight">@color/navigationDrawerTextNight</item>але як це застосовується до тексту пункту меню ?? itemTextColorне існує в стилі
Хтось десь

6

Якщо ви хочете змінити лише один пункт пункту меню з вашої активності на основі подій, загляньте цей блог від 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);
}

Метод дзвінка

setTextColorForMenuItem(item, R.color.colorPrimary);

Якщо ви працюєте з Xamarin Android, спробуйте наступне:

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

Метод дзвінка:

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

5

Ви можете програмно використовувати цей код:

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

Тепер у вікні навігації ви також можете надати власний вигляд елементів. З новим appcompat-v7:23.1.0можна

встановити власні перегляди елементів за допомогою програми: actionLayout або за допомогою MenuItemCompat.setActionView ().

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

Таким чином ви можете створити власний макет за допомогою TextView і змінювати, backgrounds/colors/fontsяк завгодно. Сподіваюся, це було корисно :) Джерело


0

Якщо ви хочете зробити це програмно:

На основі відповіді Джона:

Ви можете використовувати розширення Kotlin таким чином:

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

Тоді телефонуйте

nav_view.setTextColorForMenuItems(Color.BLACK)

-1

Ви можете зробити це за допомогою наступного твердження:

navigationView.setItemBackground(ContextCompat.getDrawable(CustomerHomeActivity.this, R.color.transparent));
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.