Змініть колір позначеного пункту меню у вікні навігації


103

Я використовую нову бібліотеку підтримки дизайну Android, щоб реалізувати навігаційний ящик у своїй програмі.

Я не можу зрозуміти, як змінити колір вибраного елемента!

Ось xml меню:

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

Ось навігація xml, яка розміщується всередині 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>

Дякую за твою допомогу !

[EDIT] Я вже розглядав такі рішення, як це: Зміна кольору фону меню Android .

Здається, це досить зламано, і я подумав, що з новою бібліотекою підтримки дизайну було б представлено щось чистіше?


Відповіді:


244

Ну, ви можете досягти цього, використовуючи Color State Resource . Якщо ви помітили всередині себе, яке NavigationViewви використовуєте

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

Тут замість @color/blackабо @color/primary_testвикористовуйте Color State List Resource. Для цього спершу створіть новий xml(наприклад, drawer_item.xml) внутрішній colorкаталог (який повинен бути всередині resкаталогу.) Якщо у вас вже немає імені color, створіть його.

Тепер всередині drawer_item.xmlзробіть щось подібне

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

Останнім кроком буде зміна вашого 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">

Як це можна використовувати окремі кольору список станів Ресурси IconTint, ItemTextColor, ItemBackground.

Тепер, коли ви встановите елемент як перевірений (або в xmlпрограмі), конкретний елемент буде мати інший колір, ніж неперевірений.


Пам’ятайте, що для натискання на роботу вам потрібно змінити його з android: state_ checked на android: state_pression.
Програміст

32
для ItemBackground вам потрібно використовувати креслення замість кольору, оскільки ви не можете визначити фон за допомогою кольорового ресурсу.
sirFunkenstine

@sash, якщо ми хочемо змінити зображення піктограми на вибраному елементі навігації, то як ми це зробимо?
mohit

@sirFunkenstine Якщо ви використовуєте селектор кольорів, ви можете помістити його у папку кольорів у вашій папці res.
Кішань Вагела

@KishanVaghela, виконуючи те, що ви пропонуєте, створює цю помилку: Бінарний файл XML-файлу №3: тег <item> вимагає атрибута "dravable" або дочірнього тега, що визначає
графічний малюнок

66

Я вважаю, що app:itemBackgroundочікує відчуття. Тому виконайте наведені нижче дії:

Створіть файл, що витягується, highlight_color.xmlіз наступним вмістом:

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

Створіть ще один файл, що витягується, nav_item_drawable.xmlіз таким вмістом:

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

Нарешті додайте app:itemBackgroundтег у 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">

тут файл select_color.xml визначає суцільний кольоровий малюнок для фону. Пізніше цей малювальний колір призначається селектору nav_item_dravable.xml.

Це працювало для мене. Сподіваємось, це допоможе.

********************************************** ОБНОВЛЕНО *** *******************************************

Хоча вищезазначена відповідь дає вам прекрасний контроль над деякими властивостями, але спосіб, який я збираюся описати, відчуває себе більш ТВЕРДО і трохи КОЛЕРНІЙ .

Тож, що ви можете зробити, ви можете визначити тему TheverOverlay у styles.xmlпрограмі NavigationView так:

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

тепер застосуйте цей ThemeOverlay до app:themeатрибуту 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:theme="@style/ThemeOverlay.AppCompat.navTheme"
app:headerLayout="@layout/drawer_header"
app:menu="@menu/menu_drawer">

Сподіваюся, це допоможе.


1
Також цей метод можна використовувати як android:background="@drawable/nav_item_drawable"для інших віджетів, таких як RadioButton, Checkbox, Button тощо. Зменшує програмування програмного забезпечення для керування setOnCheckedChangeListenerлише кольором.
rupinderjeet

@Ankush це працює, але текст і значок зникають, я також встановив колір відтінку елемента, але він не працює. Ви можете підказати, як це можна зробити
Користувач

1
@User Я не знаю, що пішло не так у вашому коді, але я додав відповідь. Зовсім інший спосіб досягти тієї ж речі з меншими зусиллями. Ви можете це перевірити.
Анкуш

1
Це слід сприймати як відповідь! Дякую дуже, дуже корисно !!!
Світлана Рожкова

4

Один необхідно встановити NavigateItemперевірив вірно , коли елемент в NavigateViewнатисканні

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

Додати NavigationItemSelectedListenerвNavigationView

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

Дякую за допомогу Вікалп, але я це вже роблю ( setChecked(true)). Я бачу, як колір перевіреного елемента змінюється, але я не можу його змінити сам, колір - це завжди легша версія фону навігаційного перегляду.
Грег

@Greg За замовчуванням setChecked(true)на Viewзміни кольору фону Шифрування до теми , що пристрій , який використовує. Якщо ви зміните фон елемента на якийсь інший колір, тоді вам слід надути макет у DrawerLayoutабо NavigationViewобробити самостійно.
Vikalp Patel

дякую ще раз, я намагався зробити те, що ви мені сказали, але без успіху, чи не було б у вас посилання, що пояснює, як будь ласка?
Грег

2

Ось ще один спосіб досягти цього:

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 стосувався того, що, якщо я хочу змінити колір вибраного пункту спливаючого меню, але завдяки вам, у мене з'явилася одна чудова ідея від вашого рішення, щоб змінити колір вибраного пункту меню ... тож даю вам голос !!! А робота навколо подібна до: item.setTitle (Html.fromHtml ("<font color = '# ff3824'> Налаштування </font>"));
Таріт Рей

1

Ось як це можна зробити в методі onCreate своєї діяльності:

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

Крок 1: Створіть перевірений / неперевірений селектор:

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>

Крок 2: використовуйте атрибут xml app:itemTextColorу NavigationViewвіджеті для вибору кольору тексту.

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

Крок 3:
Колись ви потрапляєте на елемент з якоїсь причини NavigationView, він не вважає це кнопкою перевірки. Тому потрібно перевірити вибраний елемент вручну та очистити раніше вибраний елемент. Для цього скористайтеся нижчим слухачем

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

Крок 4:
Щоб змінити колір піктограми, використовуйте app:iconTintатрибут у NavigationViewпунктах меню та встановіть той самий селектор.

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

Результат:

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.