默认效果是这样
期望的效果是这样
期望是每一行类似ConstraintLayout中的chain spread inside
第一个居左,最后一个居右,中间的每一个都居中平分剩余的空间
虚线是GridLayoutManger 默认的每个item的left
怎么实现呢,了解一下下面的计算细则?
- 默认虚线的位置是spanIndex*spanWidth
- 期望的item.left=默认虚线的位置+ItemDecoration.left
所以通过设置itemDecoration.left 就可以完成
下面直接给出计算的代码
private class AverageGridItemDecoration : RecyclerView.ItemDecoration() {
override fun getItemOffsets(
outRect: Rect,
view: View,
parent: RecyclerView,
state: RecyclerView.State
) {
super.getItemOffsets(outRect, view, parent, state)
val layoutManager = parent.layoutManager as? GridLayoutManager ?: return
val spanCount = layoutManager.spanCount
val parentWidth = parent.measuredWidth - parent.paddingStart - parent.paddingEnd
// 每一条的宽度的获取,我这里是直接写死了一个值.
// 当然你也可以动态计算或者测量出来,但是不能直接使用view.getWidth(),因为此时有可能还没有完成布局
val itemWidth = view.resources.getDimension(R.dimen.course_practice_result_item_size)
val spanWidth = parentWidth / spanCount
if (spanCount == 1) return
val spanMargin = (parentWidth - itemWidth * spanCount) / (spanCount - 1)
val spanSizeLookup = layoutManager.spanSizeLookup
val adapterPosition = parent.getChildAdapterPosition(view)
val columnIndex = spanSizeLookup.getSpanIndex(adapterPosition, spanCount)
// 核心代码:
// 左边的间距 = 期望的left- 默认的left
outRect.left =
((itemWidth + spanMargin) * columnIndex - spanWidth * columnIndex).toInt()
// 不是第一行的情况,设置上边距
if (spanSizeLookup.getSpanGroupIndex(adapterPosition, spanCount) > 0) {
outRect.top = dp2px(15f).toInt()
}
}
}