Изменить цвет отмеченного пункта меню в панели навигации
Я использую новую библиотеку Android Design Support для реализации навигационного ящика в моем приложении.
Я не могу понять, как изменить цвет выбранного элемента!
Вот 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>
Спасибо за помощь!
[РЕДАКТИРОВАТЬ] Я уже смотрел на решения, такие как это: Изменить цвет фона меню Android.
Кажется, это довольно странно, и я подумал, что с новой библиотекой поддержки проектирования что-то более чистое было бы введено?
7 ответов
Ну, вы можете добиться этого с помощью Color State Resource. Если вы заметили внутри NavigationView
вы используете
app:itemIconTint="@color/black"
app:itemTextColor="@color/primary_text"
Здесь вместо использования @color/black
или же @color/primary_test
, использовать Color State List Resource
, Для этого сначала создайте новый xml
(например, box_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
или программно), конкретный элемент будет иметь другой цвет, чем непроверенные.
Я верю 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">
здесь файл highlight_color.xml определяет сплошной цвет для фона. Позже этот цветовой рисунок назначается селектору nav_item_drawable.xml.
Это сработало для меня. Надеюсь, это поможет.
********************************************** ОБНОВЛЕНО *** *******************************************
Хотя вышеупомянутый ответ дает вам прекрасный контроль над некоторыми свойствами, но способ, который я собираюсь описать, выглядит более твердым и немного холоднее.
Так что вы можете сделать, вы можете определить ThemeOverlay в 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">
Я надеюсь, это поможет.
Нужно установить 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;
}
Шаг 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: используйте атрибут xmlapp: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>
Результат:
Вот еще один способ добиться этого:
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);
}
}
Вот как вы можете сделать это в методе 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);
если вы хотите сохранить скругление выбранного элемента в материале 3, используйте app:itemShapeFillColor="@color/main_navigation_view" вместо app:itemBackground="@color/main_navigation_view"