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


103

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

我不知道如何更改所选项目的颜色!

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

这是放置在内的navigationview 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菜单的背景颜色

这似乎是一个hack,我认为使用新的设计支持库会引入更干净的东西吗?


Answers:


244

好吧,您可以使用颜色状态资源来实现此目的。如果您发现自己NavigationView正在使用

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

在这里而不是使用@color/blackor @color/primary_test,而使用Color State List Resource。为此,首先xmlcolor目录(应该在res目录内部)中创建一个新的目录(例如,painter_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编程方式)时,特定项目的颜色将与未选中状态的颜色不同。


请记住,要使其正常工作,您需要将其从android:state_checked更改为android:state_pressed。
Programista 2015年

32
对于ItemBackground,您需要使用drawable而不是color,因为您不能使用颜色资源定义背景。
sirFunkenstine 2015年

@sash如果我们要更改所选导航项目上的图标图像,那么我们将如何执行此操作?
mohit

@sirFunkenstine如果使用的是颜色选择器,则可以将其放在res文件夹中的color文件夹中。
Kishan Vaghela

@KishanVaghela做你暗示会产生这个错误:二进制XML文件行#3:<项目>标签需要一个“绘制”属性或子标签定义绘制
iOSAndroidWindowsMo​​bileAppsDev

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

在这里,highlight_color.xml文件为背景定义了可绘制的纯色。稍后,将此颜色可绘制对象分配给nav_item_drawable.xml选择器。

这对我有用。希望这会有所帮助。

************************************************** 更新 *** ***********************************************

尽管上面提到的答案可以使您更好地控制某些属性,但是我将要描述的方式感觉更加扎实并且有点

所以你可以做的是,你可以定义一个ThemeOverlaystyles.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:themeNavigationView的属性,如下所示:

<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仅用于突出显示颜色的bloatware编程。
rupinderjeet

@Ankush可以,但是文本和图标消失了,我也设置了项目色调颜色,但是不起作用。您能建议我如何做到吗
用户

1
@User我不知道您的代码出了什么问题,但是我已经在答案中添加了。一种完全不同的方法,可以更轻松地完成同一件事。您可以检查出来。
Ankush

1
这应该作为答案!非常感谢,非常有帮助!!!
Svetlana Rozhkova

4

NavigateItem每当NavigateView单击项目中的一项时,都需要将其设置为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);

添加NavigationItemSelectedListenerNavigationView

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

感谢您对Vikalp的帮助,但我已经这样做了(setChecked(true))。我可以看到选中项的颜色发生了变化,但我自己无法对其进行修改,该颜色始终是navigatioview背景的较浅版本。
格雷格

@Greg默认情况下setChecked(true)View将背景颜色更改为您使用的设备的主题。如果要将项目的背景更改为其他颜色,则需要用DrawerLayout或扩大布局NavigationView并自行处理。
Vikalp Patel 2015年

再次感谢,我已经尽力做到了您告诉我的一切,但是没有成功,您能否通过一个链接解释您的满意程度?
格雷格

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

}


我的初衷是关于如果我想更改弹出菜单中所选项目的颜色该怎么办,但多亏您,我从您的解决方案中获得了一个很棒的主意,以更改所选菜单项的颜色...所以给您投票!解决方法就像:: :: item.setTitle(Html.fromHtml(“ <​​font color ='#ff3824'> Settings </ font>”)));
Tarit Ray

1

这是您可以在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

步骤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: 使用xml属性app:itemTextColorNavigationView插件用于选择文本的颜色。

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

结果:

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.