如何为高度不一的无限滚动RecyclerView添加居中背景黑线?
最优方案:使用RecyclerView.ItemDecoration实现
嘿,这个需求我熟得很!要在高度不一的RecyclerView列表项底部中间加黑线,还得性能拉满?RecyclerView.ItemDecoration绝对是最优解,没有之一。下面给你拆解下为什么以及怎么实现:
为什么选ItemDecoration?
这是RecyclerView原生提供的装饰扩展,专门用来处理分割线、间距这类UI装饰,优势太明显了:
- 完全不侵入item布局,不用给每个item额外加View,避免了布局层级冗余,减少Measure/Layout阶段的性能开销
- 统一在RecyclerView的绘制流程中处理装饰,比每个item单独绘制高效得多,尤其适合无限滚动这种大量item的场景
- 灵活可控,能轻松调整黑线的显示规则(比如不给最后一个item加线)
具体实现步骤
1. 自定义ItemDecoration类
我们要写一个继承自RecyclerView.ItemDecoration的类,负责计算间距并绘制中间黑线:
import android.graphics.Canvas import android.graphics.Color import android.graphics.Paint import android.graphics.Rect import android.view.View import androidx.recyclerview.widget.RecyclerView class MiddleBottomLineDecoration( private val lineWidth: Int, // 黑线的宽度(比如100dp) private val lineHeight: Int, // 黑线的高度(比如2dp) private val lineColor: Int = Color.BLACK ) : RecyclerView.ItemDecoration() { // 给item底部留出黑线的高度,防止黑线被item内容覆盖 override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) { super.getItemOffsets(outRect, view, parent, state) outRect.bottom = lineHeight } // 绘制中间黑线 override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) { super.onDraw(c, parent, state) val childCount = parent.childCount val paint = Paint().apply { color = lineColor style = Paint.Style.FILL isAntiAlias = true // 抗锯齿,让线条更平滑 } // 遍历每个可见的item,绘制对应的黑线 for (i in 0 until childCount) { val child = parent.getChildAt(i) val params = child.layoutParams as RecyclerView.LayoutParams // 计算黑线的位置:水平居中,宽度为lineWidth,位于item底部(包含margin) val lineLeft = (parent.width - lineWidth) / 2f val lineRight = lineLeft + lineWidth val lineTop = child.bottom + params.bottomMargin.toFloat() val lineBottom = lineTop + lineHeight // 绘制矩形黑线 c.drawRect(lineLeft, lineTop, lineRight, lineBottom, paint) } } }
2. 给RecyclerView添加装饰
在初始化RecyclerView的地方,把这个Decoration加进去就行:
// 从资源文件读取尺寸(推荐,方便适配) val lineWidth = resources.getDimensionPixelSize(R.dimen.middle_line_width) val lineHeight = resources.getDimensionPixelSize(R.dimen.middle_line_height) // 添加装饰 recyclerView.addItemDecoration(MiddleBottomLineDecoration(lineWidth, lineHeight))
3. 可选:控制黑线的显示规则
如果不想给最后一个item加黑线,只需要在onDraw里加个判断:
// 获取当前可见item的位置 val position = parent.getChildAdapterPosition(child) // 如果是最后一个item,跳过绘制 if (position == parent.adapter?.itemCount?.minus(1)) { continue }
为什么不推荐其他方案?
- 在item布局里加View:每个item多一个View,会增加内存占用和绘制开销,尤其无限滚动时,大量重复的View会拖慢性能
- 自定义RecyclerView:需要修改RecyclerView的绘制逻辑,复杂度高,完全没必要,原生ItemDecoration已经能完美解决
内容的提问来源于stack exchange,提问作者Tobias von Falkenhayn
相关产品推荐
相关产品推荐

