【问题标题】:Change the color of a checked menu item in a navigation drawer更改导航抽屉中选中菜单项的颜色
【发布时间】:2015-09-02 09:15:18
【问题描述】:

我正在使用新的 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,我认为使用新的设计支持库会引入一些更清洁的东西?

【问题讨论】:

标签: android androiddesignsupport


【解决方案1】:

您可以使用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">

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

现在,当您将项目设置为选中(在xml 或以编程方式)时,特定项目的颜色将与未选中的不同。

【讨论】:

  • 请记住,要使pressed工作,您需要将其从android:state_checked更改为android:state_pressed。
  • 对于 ItemBackground,您需要使用可绘制对象而不是颜色,因为您无法使用颜色资源定义背景。
  • @sash 如果我们想更改选择导航项上的图标图像,那么我们将如何做到这一点?
  • @sirFunkenstine 如果您使用颜色选择器,那么您可以将它放在 res 文件夹中的颜色文件夹中。
  • 不要忘记在您的菜单 XML 中应用“CHECKABLE=TRUE”以使背景正常工作
【解决方案2】:

我相信app:itemBackground 期望有一个drawable。所以请按照以下步骤操作:

制作一个可绘制的文件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>

最后在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">

这里的 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">

我希望这会有所帮助。

【讨论】:

  • 此外,此方法可用作 android:background="@drawable/nav_item_drawable" 用于其他小部件,如 RadioButton、Checkbox、Button 等。减少了处理 setOnCheckedChangeListener 仅用于颜色突出显示的膨胀软件编程。
  • @Ankush 这有效,但文本和图标消失了,我也设置了项目的色调颜色,但它不起作用。你能建议我怎么做吗
  • @User 我不知道您的代码出了什么问题,但我已添加到答案中。一种完全不同的方式来以更少的努力实现同样的事情。你可以去看看。
  • 这应该被接受为答案!非常感谢,非常有帮助!!!
  • 不要忘记在您的菜单 XML 中应用“CHECKABLE=TRUE”以使背景正常工作
【解决方案3】:

每当点击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;
  }

【讨论】:

  • 感谢 Vikalp 的帮助,但我已经这样做了 (setChecked(true))。我可以看到选中项的颜色在变化,但我不能自己修改,颜色总是navigatioview背景的浅色版本。
  • @Greg 默认情况下,setChecked(true) on View 将背景颜色更改为您使用的设备的主题。如果要将项目的背景更改为其他颜色,则需要在 DrawerLayoutNavigationView 中填充布局并自行处理。
  • 再次感谢,我已尝试按照您告诉我的操作,但没有成功,您能否提供一个链接说明如何操作?
【解决方案4】:

第 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 步和第 4 步:

第 3 步:要使菜单图标可检查:将所有项目包装在 &lt;group&gt; 和 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);
    }
}

【讨论】:

  • 如果我可以在第一个项目上使用不同的颜色 黄色和第二个项目上的白色 红色?
  • @Fortran 如果我理解你的话,我认为你需要为不同的导航抽屉项目使用不同的颜色;然后您可以创建多个可绘制的选择器,每个具有不同的颜色;并将app:iconTint="@drawable/selector" 与您想要的特定选择器一起使用
【解决方案5】:

这是实现此目的的另一种方法:

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("Settings"));
【解决方案6】:

您可以在 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);

【讨论】:

    【解决方案7】:

    如果要在材质 3 中保留所选项目的圆角,请使用 app:itemShapeFillColor="@color/main_navigation_view" 代替 app:itemBackground="@color/main_navigation_view"

    【讨论】:

    • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
    猜你喜欢
    • 2016-06-16
    • 2015-11-09
    • 2019-03-05
    • 1970-01-01
    • 2016-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多