如何在 NavigationView 中自定义项目背景和项目文本颜色?

我想达到这样的东西显示在 材料设计文档

colorControlHighlight用于检查项目的背景。

我需要定制:

  • 未经核实的背景资料
  • 检查文本颜色
  • 未检查文字颜色
80933 次浏览

itemBackgrounditemIconTintitemTextColor是可以设置的简单 xml 属性,不过必须使用自定义前缀而不是 android:前缀。

例子

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">


<!-- Other layout views -->


<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:itemBackground="@drawable/my_ripple"
app:itemIconTint="#2196f3"
app:itemTextColor="#009688"
app:headerLayout="@layout/nav_header"
app:menu="@menu/drawer_view" />


</android.support.v4.widget.DrawerLayout>

注意: 在这种情况下,文本颜色、图标色彩和背景是静态的。如果你想改变文本的颜色(例如未选中的粉红色和选中的青色) ,你应该使用 ColorStateList

例子

/res/color中创建一个新的 * . xml 文件(让我们把它命名为 State _ list. xml) ,其内容如下:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- This is used when the Navigation Item is checked -->
<item android:color="#009688" android:state_checked="true" />
<!-- This is the default text color -->
<item android:color="#E91E63" />
</selector>

然后像这样简单地引用它: app:itemTextColor="@color/state_list"

itemIconTint也是如此。 itemBackground需要一个资源 id。请参阅 医生

对我来说,使用 ColorControlHighlight 是一个很好的解决方案。请注意,使用最新的支持库,您可以为每个小部件定义一个主题(而不仅仅是样式) ; 例如,您可以将 ColorControlHighlight 定义到 NavigationView 主题中,而这不会应用到其他小部件。

你可以使用以下语句:

navigationView.setItemBackground(ContextCompat.getDrawable(CustomerHomeActivity.this, R.color.transparent));

现在,在导航视图中,您还可以提供自己的项目视图

通过 app: actionLayout 或使用 MenuItemCompat.setActionView ()为项目设置自定义视图。

View view = View.inflate(context, R.layout.your_custom_nav_layout_item, null);
MenuItemCompat.setActionView(menuItem, view);

通过这种方式,您可以使用 TextView 创建自己的布局,并可以随意更改 backgrounds/colors/fonts。希望这对你有帮助:) 来源

您可以通过编程方式使用以下代码:

int[][] states = new int[][] {
new int[] { android.R.attr.state_enabled}, // enabled
new int[] {-android.R.attr.state_enabled}, // disabled
new int[] {-android.R.attr.state_checked}, // unchecked
new int[] { android.R.attr.state_pressed}  // pressed
};


int[] colors = new int[] {
Color.BLACK,
Color.RED,
Color.GREEN,
Color.BLUE
};


ColorStateList myList = new ColorStateList(states, colors);


nav_view.setItemIconTintList(myList);

NavigationDrawer (NavigationView)有三个选项用于配置选中/选中的项。

app:itemIconTint="@color/menu_text_color" //icon color
app:itemTextColor="@color/menu_text_color" //text color
app:itemBackground="@drawable/menu_background_color" //background

图标和文本颜色

前两个选项(图标和文本)需要 颜色状态列表资源-https://developer.android.com/guide/topics/resources/color-list-resource.html

这样的 menu_text_color资源需要在 分辨率/颜色中创建。这个文件内容应该类似于:

<!-- res/color/menu_text_color.xml -->
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/colorWhite" android:state_checked="true" />
<item android:color="@color/colorBlack" android:state_checked="false"/>
</selector>
  • 用于检查项目的颜色资源

  • 用于未选项的颜色资源

我为两者都创建了一个资源,但是可以创建两个分离的文件——一个用于文本,一个用于图标。

背景

背景选项需要可绘制的资源而不是颜色,每次设置颜色的尝试都会以异常结束。需要在 可撤销/可提取中创建可绘制资源,其内容应类似于:

<!-- res/drawable/menu_background_color.xml -->
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/transparent"  android:state_checked="false"/>
<item android:drawable="@color/colorPrimary" android:state_checked="true"/>
</selector>

没有必要创建任何模拟颜色的绘图(在其他解决方案中我看到了这样的命题-可能是旧版本的 sdk 版本) ,颜色可以在这个文件中直接使用。在这个示例文件中,我对未选中的项使用透明颜色,对选中的项使用 colorPrimary

故障排除和重要注意事项

  • 在背景资源中始终使用 State _ check = “ false”代替默认颜色,使用默认颜色是不起作用的
  • 对于动态/程序化创建的菜单 记住把项目设置为可检查的:

代码示例(动态菜单项添加) :

  menu.add(group_id, item_id, Menu.NONE, item_name).setCheckable(true).setChecked(false);

如果项目将不会被设置为可检查,然后背景将不工作(文字和图标颜色惊人将工作预期)。

如果你只想在活动中改变一个菜单项的颜色,请看 HANIHASHEMI 的博客:

Https://hanihashemi.com/2017/05/06/change-text-color-of-menuitem-in-navigation-drawer/

private void setTextColorForMenuItem(MenuItem menuItem, @ColorRes int color) {
SpannableString spanString = new SpannableString(menuItem.getTitle().toString());
spanString.setSpan(new ForegroundColorSpan(ContextCompat.getColor(this, color)), 0, spanString.length(), 0);
menuItem.setTitle(spanString);
}

调用方法

setTextColorForMenuItem(item, R.color.colorPrimary);

如果你使用 Xamarin Android,试试这个:

private void SetTextColorForMenuItem(IMenuItem menuItem, Android.Graphics.Color color)
{
SpannableString spanString = new SpannableString(menuItem.TitleFormatted.ToString());
spanString.SetSpan(new ForegroundColorSpan(color), 0, spanString.Length(), 0);
menuItem.SetTitle(spanString);
}

致电方式:

SetTextColorForMenuItem(navigationView.Menu.GetItem(0), Android.Graphics.Color.OrangeRed);

如果希望以编程方式完成此操作:

根据约翰的回答:

你可以这样使用 Kotlin 扩展:

fun NavigationView.setTextColorForMenuItems(@ColorInt color: Int) {
for (i: Int in 0 until menu.size()) {
val menuItem = menu.getItem(i)
val spanString = SpannableString(menuItem.title.toString())
spanString.setSpan(ForegroundColorSpan(color), 0, spanString.length, 0)
menuItem.title = spanString
}
}

那就打电话

nav_view.setTextColorForMenuItems(Color.BLACK)

使用 材料组件库 ,您可以使用以下属性:

  • 背景色
  • 图标色彩
  • 字体颜色

在布局中:

<com.google.android.material.navigation.NavigationView
app:itemShapeFillColor="@color/shape_selector"
app:itemIconTint="@color/icon_tint_selector"
app:itemTextColor="@color/text_color_selector"
../>

定制风格:

<style name="..." parent="Widget.MaterialComponents.NavigationView" >
<item name="itemShapeFillColor">@color/shape_selector</item>
<item name="itemIconTint">@color/icon_tint_selector</item>
<item name="itemTextColor">@color/text_color_selector</item>
</style>

对于 itemIconTintitemTextColor,您可以使用如下选择器:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="?attr/colorPrimary" android:state_checked="true"/>
<item android:alpha="0.38" android:color="?attr/colorOnSurface" android:state_enabled="false"/>
<item android:color="?attr/colorOnSurface"/>
</selector>

对于 itemShapeFillColor,您可以使用如下选择器:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:alpha="0.12" android:color="?attr/colorPrimary" android:state_activated="true"/>
<item android:alpha="0.12" android:color="?attr/colorPrimary" android:state_checked="true"/>
<item android:color="@android:color/transparent"/>
</selector>

只有 最后一点。 注意使用 itemBackground
当设置 itemShapeAppearance和/或 itemShapeAppearanceOverlay(违约行为)时,它被设置为 @null以使用由 NavigationView以编程方式生成的形状背景。
此背景使用 itemShape*属性设置样式。
设置 itemBackground将覆盖编程背景,并导致忽略 itemShape * 属性中设置的值。

enter image description here