Android:如何单独修改NavigationView中单个列表项的背景色
我懂你想要的效果——给NavigationView里的某一个菜单项设置整个列表项的背景色,而不是只改文字那一小块的背景。你之前用SpannableString加BackgroundColorSpan的思路,确实只能作用于文本本身,要实现类似app:itemBackground那种整项背景的效果,这里有几个靠谱的方案:
方案一:自定义MenuItem布局(最推荐,灵活稳定)
这种方法能让你完全掌控单个菜单项的样式,步骤很简单:
- 先创建一个自定义的菜单项布局文件,比如
res/layout/menu_item_custom.xml:
<?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingVertical="16dp" android:paddingHorizontal="16dp" android:background="@color/colorAccent" <!-- 这里设置你要的背景色 --> android:textColor="@android:color/white" <!-- 可选:修改文字颜色适配背景 --> android:textSize="16sp" android:gravity="center_vertical"/>
- 在代码里找到目标MenuItem,给它绑定这个自定义布局:
val proItem = nav_view.menu.findItem(R.id.pro_item) // 加载自定义布局并设置给MenuItem val customView = LayoutInflater.from(this).inflate(R.layout.menu_item_custom, nav_view, false) proItem.actionView = customView // 别忘了把原标题同步到自定义视图上 (customView as TextView).text = proItem.title
这个方案的好处是,你还能在自定义布局里加图标、调整间距,完全按照需求定制样式,不会影响其他菜单项。
方案二:直接找到NavigationView的列表项视图
NavigationView的菜单底层是RecyclerView(不同版本可能有差异,但大部分是),我们可以直接定位到对应位置的View来设置背景:
// 一定要等NavigationView完成布局后再执行,所以用post延迟 nav_view.post { // 获取NavigationView内部的菜单列表视图 val menuRecyclerView = nav_view.getChildAt(0) as RecyclerView // 第一个菜单项的位置是0,如果有Header的话要改成1 val targetItemPosition = 0 if (menuRecyclerView.adapter != null && targetItemPosition < menuRecyclerView.adapter!!.itemCount) { // 获取目标项的View val targetItemView = menuRecyclerView.findViewHolderForAdapterPosition(targetItemPosition)?.itemView // 设置背景色 targetItemView?.setBackgroundColor(ContextCompat.getColor(this, R.color.colorAccent)) } }
注意:如果你的NavigationView有头部(app:headerLayout),那第一个菜单项的位置会变成1,需要对应调整targetItemPosition的值。
方案三:直接给MenuItem设置背景(高版本兼容)
如果你的APP只针对API 26及以上版本,可以直接用MenuItem的原生方法设置背景:
val proItem = nav_view.menu.findItem(R.id.pro_item) val bgDrawable = ColorDrawable(ContextCompat.getColor(this, R.color.colorAccent)) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { proItem.setBackgroundDrawable(bgDrawable) // 可选:如果图标颜色被 tint 影响,可以取消 tint proItem.setIconTintList(null) }
低版本的话需要用反射实现,但兼容性不如前两种方案,不太推荐。
内容的提问来源于stack exchange,提问作者Daniele
相关产品推荐
相关产品推荐

