RecyclerView中移除最后一行空白列的多余Item Decoration
解决RecyclerView最后一行空白列的分割线问题
方法一:修正SpanSizeLookup+自定义分割线
你的原有SpanSizeLookup逻辑存在计算漏洞(当item总数能被10整除时,lastRowCount会等于0,导致判断失效),同时默认DividerItemDecoration会给空白列也添加分割线,需要结合修正布局逻辑和自定义分割线来解决:
1. 修正GridLayoutManager的SpanSizeLookup
val manager = GridLayoutManager(context, 10) manager.spanSizeLookup = object : SpanSizeLookup() { override fun getSpanSize(position: Int): Int { val totalItems = taskDatesAdapter.itemCount val itemsInLastRow = totalItems % 10 // 处理总数能被10整除的情况,最后一行仍为10个item val lastRowItemCount = if (itemsInLastRow == 0) 10 else itemsInLastRow val isLastRow = position >= totalItems - lastRowItemCount // 所有item都保持1格宽度,仅修正布局判断逻辑 return 1 } } taskDatesView.layoutManager = manager
2. 自定义分割线跳过最后一行空白列
替换默认的DividerItemDecoration,只给有效item添加分割线:
class CustomGridDividerDecoration( context: Context, orientation: Int, private val spanCount: Int ) : RecyclerView.ItemDecoration() { private val dividerDrawable: Drawable? init { val a = context.obtainStyledAttributes(intArrayOf(android.R.attr.listDivider)) dividerDrawable = a.getDrawable(0) a.recycle() } override fun getItemOffsets( outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State ) { super.getItemOffsets(outRect, view, parent, state) val position = parent.getChildAdapterPosition(view) val totalItems = state.itemCount.takeIf { it > 0 } ?: return val itemsInLastRow = totalItems % spanCount val lastRowItemCount = if (itemsInLastRow == 0) spanCount else itemsInLastRow val isLastRow = position >= totalItems - lastRowItemCount // 水平方向:最后一行的最后一个item不添加右侧分割线 if (orientation == DividerItemDecoration.HORIZONTAL) { outRect.right = if (isLastRow && position == totalItems - 1) 0 else dividerDrawable?.intrinsicWidth ?: 0 } } override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) { super.onDraw(c, parent, state) if (orientation != DividerItemDecoration.HORIZONTAL || dividerDrawable == null) return val childCount = parent.childCount for (i in 0 until childCount) { val child = parent.getChildAt(i) val position = parent.getChildAdapterPosition(child) val totalItems = parent.adapter?.itemCount ?: 0 if (totalItems == 0) return val itemsInLastRow = totalItems % spanCount val lastRowItemCount = if (itemsInLastRow == 0) spanCount else itemsInLastRow val isLastRow = position >= totalItems - lastRowItemCount // 最后一行的最后一个item不绘制分割线 if (isLastRow && position == totalItems - 1) continue val params = child.layoutParams as RecyclerView.LayoutParams val top = child.top - params.topMargin val bottom = child.bottom + params.bottomMargin val left = child.right + params.rightMargin val right = left + dividerDrawable.intrinsicWidth dividerDrawable.setBounds(left, top, right, bottom) dividerDrawable.draw(c) } } }
然后替换原有分割线代码:
// 移除默认分割线 // taskDatesView.addItemDecoration(decoration) // 添加自定义分割线 val customDecoration = CustomGridDividerDecoration(context, DividerItemDecoration.HORIZONTAL, 10) taskDatesView.addItemDecoration(customDecoration)
方法二:让最后一行item填满整行(无空白列)
如果需求是让最后一行的item自动扩展宽度填满整行,直接修改SpanSizeLookup即可:
manager.spanSizeLookup = object : SpanSizeLookup() { override fun getSpanSize(position: Int): Int { val totalItems = taskDatesAdapter.itemCount val itemsInLastRow = totalItems % 10 if (itemsInLastRow == 0) return 1 val isLastRow = position >= totalItems - itemsInLastRow // 最后一行的每个item占对应比例的宽度,填满整行 return if (isLastRow) 10 / itemsInLastRow else 1 } }
内容的提问来源于stack exchange,提问作者Manju
相关产品推荐
相关产品推荐

