要實現(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
}
}