更改导航抽屉中选中菜单项的颜色
Change the color of a checked menu item in a navigation drawer
我正在使用新的 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>
这是放置在 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>
感谢您的帮助!
[编辑]
我已经看过这样的解决方案:Change background color of android menu.
这似乎是一个 hack,我认为使用新的设计支持库,会引入更清洁的东西吗?
只要单击 NavigateView
中的项目,就需要设置 NavigateItem
为真
//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);
在 NavigationView
上添加 NavigationItemSelectedListener
@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;
}
你可以使用 Color State Resource 来实现。如果您注意到 NavigationView
内部您正在使用
app:itemIconTint="@color/black"
app:itemTextColor="@color/primary_text"
这里不使用 @color/black
或 @color/primary_test
,而是使用 Color State List Resource
。为此,首先在 color
目录(应该在 res
目录内)中创建一个新的 xml
(例如 drawer_item.xml)。如果您没有名为 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
中或以编程方式),特定项目的颜色将与未选中的颜色不同。
这是实现此目的的另一种方法:
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);
}
}
我相信 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
标签:
<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 选择器。
这对我有用。希望这会有所帮助。
************************************************ * 已更新 *************************************** ********
虽然上面提到的答案可以让你很好地控制一些属性,但我即将描述的方式感觉更 SOLID 并且有点 COOLER.
所以您可以做的是,您可以在 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>
现在将此 ThemeOverlay 应用于 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">
希望对您有所帮助。
以下是您可以在 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);
第 1 步: 构建一个 checked/unchecked 选择器:
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: 在 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" />
第 3 步和第 4 步:
第 3 步: 要使菜单图标可检查:将所有项目包装在 <group>
中并设置 android:checkableBehavior="single"
第 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>
第 5 步::确保 onNavigationItemSelected()
回调 returns true 消费选择事件
navView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
drawerLayout.closeDrawer(GravityCompat.START);
return true;
}
});
结果:
旁注:
如果设置 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);
}
}
如果要在 material 3 中保留所选项目的圆角,请使用 app:itemShapeFillColor="@color/main_navigation_view" 而不是 app:itemBackground="@color/main_navigation_view"
我正在使用新的 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>
这是放置在 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>
感谢您的帮助!
[编辑] 我已经看过这样的解决方案:Change background color of android menu.
这似乎是一个 hack,我认为使用新的设计支持库,会引入更清洁的东西吗?
只要单击 NavigateView
中的项目,就需要设置 NavigateItem
为真
//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);
在 NavigationView
NavigationItemSelectedListener
@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;
}
你可以使用 Color State Resource 来实现。如果您注意到 NavigationView
内部您正在使用
app:itemIconTint="@color/black"
app:itemTextColor="@color/primary_text"
这里不使用 @color/black
或 @color/primary_test
,而是使用 Color State List Resource
。为此,首先在 color
目录(应该在 res
目录内)中创建一个新的 xml
(例如 drawer_item.xml)。如果您没有名为 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
中或以编程方式),特定项目的颜色将与未选中的颜色不同。
这是实现此目的的另一种方法:
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);
}
}
我相信 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
标签:
<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 选择器。
这对我有用。希望这会有所帮助。
************************************************ * 已更新 *************************************** ********
虽然上面提到的答案可以让你很好地控制一些属性,但我即将描述的方式感觉更 SOLID 并且有点 COOLER.
所以您可以做的是,您可以在 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>
现在将此 ThemeOverlay 应用于 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">
希望对您有所帮助。
以下是您可以在 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);
第 1 步: 构建一个 checked/unchecked 选择器:
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: 在 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" />
第 3 步和第 4 步:
第 3 步: 要使菜单图标可检查:将所有项目包装在 <group>
中并设置 android:checkableBehavior="single"
第 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>
第 5 步::确保 onNavigationItemSelected()
回调 returns true 消费选择事件
navView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
drawerLayout.closeDrawer(GravityCompat.START);
return true;
}
});
结果:
旁注:
如果设置 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);
}
}
如果要在 material 3 中保留所选项目的圆角,请使用 app:itemShapeFillColor="@color/main_navigation_view" 而不是 app:itemBackground="@color/main_navigation_view"