[英]Change the color of a checked menu item in a navigation drawer
I am using the new Android Design Support library to implement a navigation drawer in my application.我正在使用新的 Android 设计支持库在我的应用程序中实现导航抽屉。
I can't figure out how to change the color of a selected item!我不知道如何更改所选项目的颜色!
Here is the xml of the menu :这是菜单的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>
And here is the navigationview xml which is placed inside a android.support.v4.widget.DrawerLayout
:这是放置在android.support.v4.widget.DrawerLayout
的导航视图 xml:
<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>
Thank you for your help !感谢您的帮助 !
[EDIT] I have already looked at solutions such as this one : Change background color of android menu . [编辑] 我已经看过这样的解决方案: 更改 android 菜单的背景颜色。
It seems to be quite a hack and I thought that with the new Design Support Library, something cleaner would have been introduced?这似乎是一个黑客,我认为使用新的设计支持库,会引入一些更干净的东西?
Well you can achieve this using Color State Resource .那么你可以使用Color State Resource来实现这一点。 If you notice inside your NavigationView
you're using如果您注意到您正在使用的NavigationView
app:itemIconTint="@color/black"
app:itemTextColor="@color/primary_text"
Here instead of using @color/black
or @color/primary_test
, use a Color State List Resource
.这里不使用@color/black
或@color/primary_test
,而是使用Color State List Resource
。 For that, first create a new xml
(eg drawer_item.xml) inside color
directory (which should be inside res
directory.) If you don't have a directory named color
already, create one.为此,首先在color
目录(应该在res
目录中)内创建一个新的xml
(例如 drawer_item.xml)。如果您还没有名为color
的目录,请创建一个。
Now inside drawer_item.xml
do something like this现在在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>
Final step would be to change your NavigationView
最后一步是更改您的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">
Like this you can use separate Color State List Resources for IconTint
, ItemTextColor
, ItemBackground
.像这样,您可以为IconTint
、 ItemTextColor
、 ItemBackground
使用单独的颜色状态列表资源。
Now when you set an item as checked (either in xml
or programmatically), the particular item will have different color than the unchecked ones.现在,当您将项目设置为已选中(在xml
或以编程方式)时,特定项目的颜色将与未选中的项目不同。
I believe app:itemBackground
expects a drawable.我相信app:itemBackground
需要可绘制。 So follow the steps below :因此,请按照以下步骤操作:
Make a drawable file highlight_color.xml
with following contents :使用以下内容制作可绘制文件highlight_color.xml
:
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="YOUR HIGHLIGHT COLOR"/>
</shape>
Make another drawable file nav_item_drawable.xml
with following contents:使用以下内容制作另一个可绘制文件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>
Finally add app:itemBackground
tag in the NavView :最后在app:itemBackground
添加app:itemBackground
标签:
<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">
here the highlight_color.xml file defines a solid color drawable for the background.此处的 highlight_color.xml 文件定义了可绘制背景的纯色。 Later this color drawable is assigned to nav_item_drawable.xml selector.稍后将此颜色可绘制对象分配给 nav_item_drawable.xml 选择器。
This worked for me.这对我有用。 Hopefully this will help.希望这会有所帮助。
********************************************** UPDATED ********************************************** **********************************************更新*** ************************************************
Though the above mentioned answer gives you fine control over some properties, but the way I am about to describe feels more SOLID and is a bit COOLER .虽然上面提到的答案让你可以很好地控制一些属性,但我将要描述的方式感觉更可靠,有点酷。
So what you can do is, you can define a ThemeOverlay in the styles.xml
for the NavigationView like this :所以你可以做的是,你可以在styles.xml
为NavigationView定义一个ThemeOverlay ,如下所示:
<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>
now apply this ThemeOverlay to app:theme
attribute of NavigationView, like this:现在将此 ThemeOverlay app:theme
到 NavigationView 的app:theme
属性,如下所示:
<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">
I hope this will help.我希望这将有所帮助。
One need to set NavigateItem
checked true whenever item in NavigateView
is clicked每当单击NavigateView
中的项目时,需要将NavigateItem
设置为 true
//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);
Add NavigationItemSelectedListener
on NavigationView
添加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;
}
Here is the another way to achive this:这是实现此目的的另一种方法:
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);
}
} }
Step 1: Build a checked/unchecked selector:第 1 步:构建一个选中/未选中的选择器:
selector.xml选择器.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>
Step 2: use the XML
attribute app:itemTextColor
within NavigationView
widget for selecting the text color.第 2 步:使用NavigationView
小部件中的XML
属性app:itemTextColor
来选择文本颜色。
<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" />
Step 3 & 4:第 3 步和第 4 步:
Step 3: To make menu icons check-able: wrap all items in a <group>
and set android:checkableBehavior="single"
第 3 步:要使菜单图标可检查:将所有项目包装在<group>
并设置android:checkableBehavior="single"
Step 4: To change icon color: set the selector to all the items with app:iconTint
第 4 步:更改图标颜色:将选择器设置为带有app:iconTint
所有项目
<?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">
<group android:checkableBehavior="single">
<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" />
</group>
</menu>
Result:结果:
Side Note:边注:
If setting android:checkableBehavior="single"
not working, then you handle this programmatically by manually making the selected item checked and clear the previously selected item:如果设置android:checkableBehavior="single"
不起作用,那么您可以通过手动检查所选项目并清除先前选择的项目来以编程方式处理此问题:
@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);
}
}
Here's how you can do it in your Activity's onCreate method:以下是在 Activity 的 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);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.