选中的导航抽屉项背景颜色

42

我使用Android Studio实现导航抽屉,但是我无法更改用于显示当前所在部分的蓝色颜色。

我尝试了很多方法,目前正在使用以下样式:

<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_activated="true" android:drawable="@color/selected" />
    <item android:state_pressed="true" android:drawable="@color/highlight" />


</selector>

我还尝试了state_checked。在这种情况下,state_pressed可以起作用,但是当前选定的项仍然是蓝色。

编辑: 我仔细检查了一下,在创建适配器时传递的上下文是getActionBar().getThemedContext(),因此我认为如果我能找到正确的属性来分配给我的操作栏样式,我就可以从那里更改它。我已经尝试了几个不同的属性,但都没有成功。有人知道确切的属性吗?

我也意识到,如果我把

<item name="android:activatedBackgroundIndicator">@drawable/nav_listview_selector</item>

放在主题的主要部分,并将getActionBar().getThemedContext()更改为getActivity.getBaseContext,那么我就可以更改颜色,但我不认为这是正确的方法。我认为应该使用主题化的上下文。因此,如果有人知道activatedBackgroundIndicator应该放在哪里,以便在getActionBar.getThemedContext()中使用,请告诉我。

编辑2:

因此,用于列表视图的文本视图是 SDK 中的一个视图,它看起来像这样:

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/text1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textAppearance="?android:attr/textAppearanceListItemSmall"
    android:gravity="center_vertical"
    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
    android:background="?android:attr/activatedBackgroundIndicator"
    android:minHeight="?android:attr/listPreferredItemHeightSmall"
/>

我尝试在主题级别修改"?android:attr/activatedBackgroundIndicator",但它对选中/已选/激活状态没有影响,但对按下状态有影响。有人知道这是为什么吗?我该如何改变它?


我最终使用了state_selected(除了您提到的checkedpressed之外)+ ListView.setItemChecked。这花费了我很长时间,所以我可能定义了太多状态。 - velis
我觉得我已经在某个时候尝试过那个了。setItemChecked 作为 Android Studio 自动实现的一部分而被使用。 - RyanJohnstone
当我使用Android Studio的默认导航抽屉实现时,导航抽屉中当前活动片段的标题会被突出显示为蓝色,我想将该蓝色更改为我应用程序中使用的颜色,并且仅对所选项目使字体加粗。也许是我正在使用的背景xml文件。目前它将颜色更改和粗体文本应用于导航抽屉中的每个项目。 - Chris D
13个回答

52
为了解决这个问题:
1- 你不需要在ListView下使用android:listSelector。
2- 打开(或创建)(res/values)下的styles.xml。
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <!-- Customize your theme here. -->
    <item name="android:activatedBackgroundIndicator">@drawable/drawer_list_selector</item>
</style>

3- 在res/drawable文件夹下创建drawer_list_selector.xml文件

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:drawable="@drawable/light_gray_color" />
    <item android:state_activated="true" android:drawable="@drawable/red_color" />
    <item android:drawable="@android:color/transparent" />
</selector>

4- 在res/drawable下创建 red_color.xml / light_gray_color.xml(或者其他任意名称),并添加你想要的十六进制颜色:

4- 在res/drawable下创建red_color.xml / light_gray_color.xml(或任何其他名称),并添加所需的十六进制颜色:

<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="#C8FF0000"/>
</shape>

5- 打开您的项目AndroidManifest.xml文件,如果不存在,则添加android:theme标签。

返回内容:

5- 打开您的项目AndroidManifest.xml文件,如果不存在,则添加android:theme标签。

<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >

参考/引用:从默认蓝色更改导航抽屉选定项颜色


1
问题解决了!谢谢 :) - oxyt
3
这就是答案,这就是你在寻找的答案。本站关于此问题的其他答案都绕弯子回答,而这个答案是最容易实现且能获得最好结果的。 - Muhammad Abdul-Rahim
5
对我来说这并不奏效。与当前活动相对应的列表项没有以其相应的颜色绘制(我猜在你的代码中是红色)。 - Flame of udun
5
是的,它对我起作用了。只有在导航抽屉中设置itemBackground="@drawable/drawer_list_selector",而不是在AppTheme中调用它。还要在onNavigationItemSelected(MenuItem item)中使用item.setCheckable(true);和item.setChecked(true);。 - Pratik Saluja
1
不支持Android O,背景仍然是灰色的 :( - kashlo
显示剩余2条评论

13

如果您想要更改"Navigation Drawer item background colour for selected item"的颜色,可以使用属性:

colorControlHighlight

在您的"styles.xml"中,可以像这样显示:

<style name="YourStyleNameFor.NavigationDrawer" parent="ThemeOverlay.AppCompat.Light">
    <item name="colorControlHighlight">@color/your_highlight_color</item>
</style>

别忘了在tag中应用您的Style

android.support.design.widget.NavigationView

例如,在activity_main.xml中,它可能看起来像这样:

<android.support.design.widget.NavigationView
    android:id="@+id/nav_view"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:fitsSystemWindows="true"
    app:headerLayout="@layout/navigationdrawer_header"

    <!-- the following line referes to your style  -->
    app:theme="@style/YourThemeNameFor.NavigationDrawer"

    <!-- the following two lines are maybe also interesting for you -->
    app:itemIconTint="@color/gray3"
    app:itemTextColor="@color/gray3"

    app:menu="@menu/navigationdrawer_main" />

10

这对我有用:

  1. 首先,定义一个可绘制的 item_bg.xml 如下:

<?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:state_checked="true" android:drawable="@drawable/nav_menu_bg" />
    </selector>
然后在 navigation_main_layout.xml 中使用此 drawable,例如:
<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:itemBackground="@drawable/item_bg"
    android:fitsSystemWindows="true"
    app:headerLayout="@layout/nav_header_navigation"
    app:menu="@menu/navigation_main_layout_drawer" />

app:itemBackground="@drawable/item_bg" 这对我有效...谢谢 - Wasi Sadman

6
这是我完成并且有效的方法,简要概述如下:在适配器中维护所选项目的位置,并在调用 notifyDatasetChanged 时调用 notifyDataSetChanged ,这样会再次调用 getView 方法,在 getView 中检查所选位置上的位置变化并更改背景视图。以下是代码:

导航抽屉列表视图的适配器

public class MenuAdapter extends BaseAdapter {

private static final int TYPE_HEADER = 0;
private static final int TYPE_ITEM = 1;
private Context mContext;
private String name;
private int profile;
private int mIcons[];
private int selectedPosition = 0;
private String mNavTitles[];
private LayoutInflater mInflater;

public MenuAdapter(String titles[], int icon[], String Name, int profile) {
    mNavTitles = titles;
    mIcons = icon;
    name = Name;
    this.profile = profile;
}

public MenuAdapter(String Titles[], int Icons[], Context mContext) {
    mNavTitles = Titles;
    mIcons = Icons;
    this.mContext = mContext;
    mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

@Override
public int getCount() {
    return mNavTitles.length;
}

@Override
public Object getItem(int position) {
    return position;
}

@Override
public long getItemId(int position) {
    return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    convertView = mInflater.inflate(R.layout.item_row, parent, false);

    TextView textView = (TextView) convertView.findViewById(R.id.rowText);
    ImageView imageView = (ImageView) convertView.findViewById(R.id.rowIcon);
    final LinearLayout layout = (LinearLayout) convertView.findViewById(R.id.outerLayout);

    imageView.setImageResource(mIcons[position]);
    textView.setText(mNavTitles[position]);

    if (position == selectedPosition)
        layout.setBackgroundColor(mContext.getResources().getColor(R.color.app_bg));
    else  
      layout.setBackgroundColor(mContext.getResources().getColor(R.color.normal_bg));

    return convertView;
}

public void setSelectedPosition(int position) {

    this.selectedPosition = position;

}


}

在你的活动中,执行以下操作:
 private class DrawerItemClickListener implements ListView.OnItemClickListener {
    @Override
    public void onItemClick(AdapterView parent, View view, int position, long id) { 
        mMenuAdapter.setSelectedPosition(position - 1);
        mMenuAdapter.notifyDataSetChanged();
    }
}

如果有人仍然遇到困难,请随时询问。

2
@ayz4sci:请不要在这个答案的代码中胡乱更改。如果您想对解决方案提出改进意见,那么请给回答者留言(以便他们可以改进),或者提供您自己的答案(仅当合理时,即它提供了根本性的改进)。 - honk
谢谢你的正确指出,@ayz4sci。如果我们在适配器中重用视图并且没有编写else部分,则会突出显示多个选项,因此需要else部分。非常感谢您的努力。 - Syed Raza Mehdi
在我写第一个评论的时候,@ayz4sci又提出了另一个编辑建议,他们再一次更改了带有normal_bg的那行代码,改用了一个transparent颜色。因此,我认为这些建议过于试验性了。如果你和他们讨论后再应用更改,会更好一些。 - honk

5

我使用自定义适配器类实现了抽屉菜单。也许能对某些人有所帮助。抽屉列表

<ListView
    android:id="@+id/listview_drawer"
    android:layout_width="260dp"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:background="@color/menu_item_color"
    android:choiceMode="singleChoice"
    android:divider="@android:color/transparent"
    android:dividerHeight="0dp"
    android:fadingEdge="none"
    />

drawer_list_item.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content" 
android:background="@drawable/menu_selector"
>

<ImageView
    android:id="@+id/imgIcon"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerVertical="true"
    android:layout_marginLeft="12dp"
    android:layout_marginRight="12dp"
    android:src="@drawable/ic_menu_home" />

<TextView
    android:id="@+id/lblName"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_centerVertical="true"
    android:gravity="center_vertical"
    android:layout_toRightOf="@+id/imgIcon"
    android:minHeight="48dp"
    android:textColor="@color/menu_txt_color" />

menu_selector.xml

<selector xmlns:android="http://schemas.android.com/apk/res/android" android:exitFadeDuration="@android:integer/config_mediumAnimTime">
<!-- selected -->
<item android:drawable="@color/menu_item_active_color" android:state_focused="true" android:state_pressed="false"/>
<item android:drawable="@color/menu_item_active_color" android:state_pressed="true"/>
<item android:drawable="@color/menu_item_active_color" android:state_activated="true"/>
<item android:drawable="@color/menu_item_active_color" android:state_checked="true"/>
<item android:drawable="@color/menu_item_active_color" android:state_selected="true"/>

<item android:drawable="@color/menu_item_color" android:state_activated="false"/>

在ListView的项目点击监听器中添加以下内容:yourlistview.setItemChecked(position, true);

2
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
   <item android:drawable="@color/list_item_back_pressed" android:state_pressed="true" />
    <item  android:state_activated="true"><color android:color="@color/primary_blue"/></item>
   <item android:drawable="@color/list_item_back_normal"/>

</selector>

0
我知道现在有点晚了,但是我已经解决了我的应用程序中的这个问题。 请不要觉得它很傻,只需将“state_pressed”的位置简单地改为顶部即可。
<item android:drawable="@drawable/list_item_bg_pressed" android:state_pressed="true"/>
<item android:drawable="@drawable/list_item_bg_normal" android:state_activated="false"/>
<item android:drawable="@drawable/list_item_bg_selected" android:state_activated="true"/>

0

如果将来有人使用导航抽屉活动(由工作室在活动提示窗口中提供)

答案是 -

在MainActivity的OnCreate()之前使用此代码

    int[][] state = new int[][] {
            new int[] {android.R.attr.state_checked}, // checked
            new int[] {-android.R.attr.state_checked}
    };

    int[] color = new int[] {
            Color.rgb(255,46,84),
            (Color.BLACK)
    };

    ColorStateList csl = new ColorStateList(state, color);

    int[][] state2 = new int[][] {
            new int[] {android.R.attr.state_checked}, // checked
            new int[] {-android.R.attr.state_checked}
    };

    int[] color2 = new int[] {
            Color.rgb(255,46,84),
            (Color.GRAY)
    };

ColorStateList csl2 = new ColorStateList(state2, color2);

然后在MainActivity的onNavigationItemSelected()中使用它(如果您使用导航抽屉活动,则无需编写此函数,它将添加到MainActivity中)。

 NavigationView nav = (NavigationView) findViewById(R.id.nav_view);
    nav.setItemTextColor(csl);
    nav.setItemIconTintList(csl2);
    nav.setItemBackgroundResource(R.color.white);

提示 - 在onNavigationItemSelected()方法中的if else条件语句之前添加此代码


0
这对我有用: 通过使用菜单项而不是使用列表填充导航视图来实现菜单抽屉。
创建了一个像这样的可绘制对象:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/drawer_menu_selector_color" android:state_checked="true"></item>
<item android:drawable="@color/drawer_menu_selector_color" android:state_activated="true"></item>

在onCreate方法中,将对应于所选活动的菜单项的ID设置为已选中。并像这样将可绘制选择器文件实现到您的导航抽屉中。
    app:itemBackground="@drawable/drawer_menu_selector"

提示:需要定义您的“app”命名空间。


0

在SO上,您应该指出此链接提供了答案。仅提供链接的回答是不合法的。 - Bùi Đức Khánh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接