GridLayoutManager怎么居中?

默认效果是这样


屏幕截图 2021-02-22 230949.png

期望的效果是这样


clipboard.png

期望是每一行类似ConstraintLayout中的chain spread inside

image.png

第一个居左,最后一个居右,中间的每一个都居中平分剩余的空间
虚线是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()
        }

    }
}

Demo 地址: https://github.com/pokercc/GridLayoutMangerDemo

推荐阅读更多精彩内容