简体   繁体   English

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

[英]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 .像这样,您可以为IconTintItemTextColorItemBackground使用单独的颜色状态列表资源。

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

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM