RecyclerView使用GridLayoutManager時,分區(qū)域顯示背景

要實現(xiàn)的效果:

使用一個GridLayoutManager,將item分成title和normal兩種類型,title的spanSize是3,normal的spanSize是1。
每個區(qū)域的上下邊距和區(qū)域內(nèi)的邊距長度稍有不同

image

實現(xiàn)思路:

遍歷view,如果是每一列的第一個view就繼續(xù)
判斷條目是標(biāo)題還是要畫背景的條目,如果是要畫背景的條目,判斷條目所在位置。
具體情況分為:1. 該行是一塊里面的第一行、中間行、最后行 2. 該行是獨立的一塊
分情況畫背景

實現(xiàn)代碼:


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不畫
             * 普通的判斷每一行的第一個
             *    如果在第一行 且行數(shù)>1 畫上半部分  第一行 判斷,上一個的spanCount是3
             *    如果在第一行 且行數(shù)=1 畫圓       行數(shù)是否>1 判斷position+1 +2 +3的spanSize都是1
             *    如果在第一行往后 且后面還有 畫方塊 行數(shù)>1判斷
             *    如果在最后一行 畫下半部分         行數(shù)>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個以內(nèi)發(fā)現(xiàn)占位是3的標(biāo)題,就是沒有上一行
        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個以內(nèi)第一個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
    }
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • PK賽 第六天 今天上午注定是難熬的一上午,早早起床又空講了2遍,然后早早到了比賽場地,準(zhǔn)備室被前幾個講課的用著的...
    一日三省吾身閱讀 136評論 0 2
  • 浙江省公共數(shù)據(jù)條例 日期: 2022- 02- 10 18: 25 來源: 浙江省人民代表大會常務(wù)委員會 浙江省公...
    33d686a71aaa閱讀 219評論 0 0
  • 流程結(jié)構(gòu) 條件語句當(dāng)成程序中設(shè)定某一個條件滿足才執(zhí)行的語句 if(條件語句){代碼段1}else{代碼段2}條件語...
    胖胖胖虎閱讀 218評論 0 0
  • 像操作一部機(jī)器那樣,進(jìn)行管理,以實現(xiàn)目標(biāo)。 5個步驟,1樹立目標(biāo),2發(fā)現(xiàn)問題,3診斷練發(fā)現(xiàn)問題根源,4設(shè)計改進(jìn)方案...
    Rite_芳姐姐閱讀 349評論 0 0
  • 初識山姆 我說的山姆不是人物,也不是地名,更不是動物,而是美國的一個大型購物超市。 山姆與Costco是同類型的,...
    大翁閱讀 372評論 4 5