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

实现思路:
遍历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
}
}
网友评论