美文网首页
RecyclerView使用GridLayoutManager时

RecyclerView使用GridLayoutManager时

作者: da7091fa95b5 | 来源:发表于2022-03-02 16:21 被阅读0次

要实现的效果:

使用一个GridLayoutManager,将item分成title和normal两种类型,title的spanSize是3,normal的spanSize是1。
每个区域的上下边距和区域内的边距长度稍有不同

image

实现思路:

遍历view,如果是每一列的第一个view就继续
判断条目是标题还是要画背景的条目,如果是要画背景的条目,判断条目所在位置。
具体情况分为:1. 该行是一块里面的第一行、中间行、最后行 2. 该行是独立的一块
分情况画背景

实现代码:


class AiInsuranceAllToolsItemDecoration : ItemDecoration() {
    override fun onDraw(
        c: Canvas, parent: RecyclerView,
        state: RecyclerView.State
    ) {
        val childCount = parent.childCount
        for (ix in 0 until childCount) {
            val child = parent.getChildAt(ix)
            val position = parent.getChildAdapterPosition(child)
            val layoutManager = parent.layoutManager as GridLayoutManager
            val spanCount = layoutManager.spanCount
            val spanSizeLookup = layoutManager.spanSizeLookup
            val spanSize = spanSizeLookup.getSpanSize(position)
            val spanIndex = spanSizeLookup.getSpanIndex(
                position,
                spanCount
            )
            if (spanSize != 1 || spanIndex != 0) {
                continue
            }
            /*
             * title不画
             * 普通的判断每一行的第一个
             *    如果在第一行 且行数>1 画上半部分  第一行 判断,上一个的spanCount是3
             *    如果在第一行 且行数=1 画圆       行数是否>1 判断position+1 +2 +3的spanSize都是1
             *    如果在第一行往后 且后面还有 画方块 行数>1判断
             *    如果在最后一行 画下半部分         行数>1判断
             * */
            val hasNextLine = hasNextLine(spanSizeLookup, position, spanCount)
            val hasLastLine = hasLastLine(spanSizeLookup, position, spanCount)
            val type = if (hasLastLine) {
                if (hasNextLine) {
                    // 方块
                    2
                } else {
                    // 最后一行
                    3
                }
            } else {
                // 没有上一行
                if (hasNextLine) {
                    // 第一行
                    1
                } else {
                    // 最后一行
                    0
                }
            }
            val drawable = generateDrawable(type)
            drawable.setBounds(
                child.left,
                if (hasLastLine) child.top else child.top - mOutSize,
                child.left + child.width * spanCount,
                if (hasNextLine) child.bottom else child.bottom + mOutSize
            )
            drawable.draw(c)
        }
    }

    private fun hasLastLine(
        spanSizeLookup: GridLayoutManager.SpanSizeLookup,
        position: Int,
        spanCount: Int
    ): Boolean {
        // 3个以内发现占位是3的标题,就是没有上一行
        for (i in 1..spanCount) {
            if (spanSizeLookup.getSpanSize(position - i) != 1) {
                return false
            }
        }
        return true
    }

    private fun hasNextLine(
        spanSizeLookup: GridLayoutManager.SpanSizeLookup,
        position: Int,
        spanCount: Int
    ): Boolean {
        // 判断3个以内第一个group不一样的条目的spanSize
        val spanGroupIndex = spanSizeLookup.getSpanGroupIndex(position, spanCount)
        for (i in 1..spanCount) {
            if (spanSizeLookup.getSpanGroupIndex(position + i, spanCount) != spanGroupIndex) {
                return spanSizeLookup.getSpanSize(position + i) == 1
            }
        }
        return true
    }

    override fun getItemOffsets(
        outRect: Rect,
        view: View,
        parent: RecyclerView,
        state: RecyclerView.State
    ) {
        super.getItemOffsets(outRect, view, parent, state)
        // 每一组的第一排top+15 最后一排bottom+15
        val position = parent.getChildAdapterPosition(view)
        val gridLayoutManager = parent.layoutManager as GridLayoutManager
        val spanSizeLookup = gridLayoutManager.spanSizeLookup
        val spanSize = spanSizeLookup.getSpanSize(position)
        if (spanSize != 1) {
            return
        }
        val spanCount = gridLayoutManager.spanCount
        val hasLastLine = hasLastLine(spanSizeLookup, position, spanCount)
        val hasNextLine = hasNextLine(spanSizeLookup, position, spanCount)
        if (!hasLastLine) {
            // 第一排
            outRect.top = mOutSize
        }
        if (!hasNextLine) {
            outRect.bottom = mOutSize
        }
    }

    private val mCornerRadius: Float = getApplication().dimenPxOffset(R.dimen.x20).toFloat()
    private val mOutSize: Int = getApplication().dimenPxOffset(R.dimen.x15)

    /**
     * /外矩形 0 四角圆弧 1 上半部分  2 方块  3 下半部分
     */
    private fun generateDrawable(type: Int): GradientDrawable {
        val gd = GradientDrawable()
        gd.cornerRadii = when (type) {
            0 -> floatArrayOf(
                mCornerRadius,
                mCornerRadius,
                mCornerRadius,
                mCornerRadius,
                mCornerRadius,
                mCornerRadius,
                mCornerRadius,
                mCornerRadius,
            )
            1 -> floatArrayOf(
                mCornerRadius,
                mCornerRadius,
                mCornerRadius,
                mCornerRadius,
                0F,
                0F,
                0F,
                0F,
            )
            2 -> floatArrayOf(
                0F,
                0F,
                0F,
                0F,
                0F,
                0F,
                0F,
                0F,
            )
//            3,
            else -> floatArrayOf(
                0F,
                0F,
                0F,
                0F,
                mCornerRadius,
                mCornerRadius,
                mCornerRadius,
                mCornerRadius,
            )
        }
        gd.setColor(Color.WHITE)
        return gd
    }
}

相关文章

网友评论

      本文标题:RecyclerView使用GridLayoutManager时

      本文链接:https://www.haomeiwen.com/subject/kyferrtx.html