更改导航抽屉中选中的菜单项的颜色

我正在使用新的 Android 设计支持库在我的应用程序中实现一个导航抽屉。

I can't figure out how to change the color of a selected item!

下面是菜单的 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>

谢谢你的帮助!

[编辑] 我已经研究过这样的解决方案: 更改 android 菜单的背景颜色

这似乎是一个相当黑客和我认为,与新的设计支持库,更干净的东西将被引入?

119996 次浏览

每当单击 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);

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

你可以使用 颜色状态资源来达到这个目的。如果你注意到在你的 NavigationView里面你正在使用

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

这里不使用 @color/black@color/primary_test,而是使用 Color State List Resource。为此,首先在 color目录(应该位于 res目录中)中创建一个新的 xml(例如  轮抽屉 _ 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">

像这样,您可以为 IconTintItemTextColorItemBackground使用单独的颜色状态列表资源。

现在,当您将一个项目设置为选中(无论是在 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期望的是一个可绘制的,所以按照下面的步骤:

Make a drawable file highlight_color.xml with following contents :

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

最后在 NavView 中添加 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">

在这里, 高亮 _ color. xml 文件為背景定義了一個固定的色彩。稍后,这个颜色绘制将分配给 nav _ item _ draable.xml 选择器。

这对我有用,希望能有帮助。

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

虽然上面提到的答案可以让你很好地控制一些属性,但是我将要描述的方式感觉更 SOLID,有点 冷却器

所以你可以这样做,你可以在 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 应用到 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: 构建一个选中/未选中的选择器:

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: 要使菜单图标可检查: 在 <group>和 setandroid: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()回调返回 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);
}
}

如果你想在材料3中保留所选项目的片段,请使用 app: itemShapeFillColor = “@color/main _ ”而不是 app: itemBack = “@color/main _ ”