DividerItemDecoration类
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Rect
import android.view.View
import androidx.annotation.ColorInt
import androidx.recyclerview.widget.RecyclerView
abstract class DividerItemDecoration : RecyclerView.ItemDecoration() {
private val mPaint by lazy { Paint(Paint.ANTI_ALIAS_FLAG) }
abstract fun getDivider(itemPosition: Int): Divider
init {
mPaint.style = Paint.Style.FILL
}
override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
//left, top, right, bottom
val childCount = parent.childCount
for (i in 0 until childCount) {
val child = parent.getChildAt(i)
val itemPosition = (child.layoutParams as RecyclerView.LayoutParams).viewLayoutPosition
val divider = getDivider(itemPosition)
divider.leftSideLine?.let {
val leftLineWidthPx = it.widthPx
if (leftLineWidthPx > 0) {
val startPaddingPx = it.startPaddingPx
val endPaddingPx = it.endPaddingPx
drawChildLeftVertical(child, c, it.color, leftLineWidthPx, startPaddingPx, endPaddingPx)
}
}
divider.topSideLine?.let {
val topLineWidthPx = it.widthPx
if (topLineWidthPx > 0) {
val startPaddingPx = it.startPaddingPx
val endPaddingPx = it.endPaddingPx
drawChildTopHorizontal(child, c, it.color, topLineWidthPx, startPaddingPx, endPaddingPx)
}
}
divider.rightSideLine?.let {
val rightLineWidthPx = it.widthPx
if (rightLineWidthPx > 0) {
val startPaddingPx = it.startPaddingPx
val endPaddingPx = it.endPaddingPx
drawChildRightVertical(child, c, it.color, rightLineWidthPx, startPaddingPx, endPaddingPx)
}
}
divider.bottomSideLine?.let {
val bottomLineWidthPx = it.widthPx
if (bottomLineWidthPx > 0) {
val startPaddingPx = it.startPaddingPx
val endPaddingPx = it.endPaddingPx
drawChildBottomHorizontal(child, c, it.color, bottomLineWidthPx, startPaddingPx, endPaddingPx)
}
}
}
}
private fun drawChildBottomHorizontal(child: View, c: Canvas, @ColorInt color: Int, lineWidthPx: Int, startPaddingPx: Int, endPaddingPx: Int) {
val leftPadding = if (startPaddingPx <= 0) {
//padding<0当作==0处理
//上下左右默认分割线的两头都出头一个分割线的宽度,避免十字交叉的时候,交叉点是空白
-lineWidthPx
} else {
startPaddingPx
}
val rightPadding = if (endPaddingPx > 0) {
-endPaddingPx
} else {
lineWidthPx
}
val params = child
.layoutParams as RecyclerView.LayoutParams
val left = child.left - params.leftMargin + leftPadding
val right = child.right + params.rightMargin + rightPadding
val top = child.bottom + params.bottomMargin
val bottom = top + lineWidthPx
mPaint.color = color
c.drawRect(left.toFloat(), top.toFloat(), right.toFloat(), bottom.toFloat(), mPaint)
}
private fun drawChildTopHorizontal(child: View, c: Canvas, @ColorInt color: Int, lineWidthPx: Int, startPaddingPx: Int, endPaddingPx: Int) {
val leftPadding = if (startPaddingPx <= 0) {
-lineWidthPx
} else {
startPaddingPx
}
val rightPadding = if (endPaddingPx <= 0) {
lineWidthPx
} else {
-endPaddingPx
}
val params = child
.layoutParams as RecyclerView.LayoutParams
val left = child.left - params.leftMargin + leftPadding
val right = child.right + params.rightMargin + rightPadding
val bottom = child.top - params.topMargin
val top = bottom - lineWidthPx
mPaint.color = color
c.drawRect(left.toFloat(), top.toFloat(), right.toFloat(), bottom.toFloat(), mPaint)
}
private fun drawChildLeftVertical(child: View, c: Canvas, @ColorInt color: Int, lineWidthPx: Int, startPaddingPx: Int, endPaddingPx: Int) {
val topPadding = if (startPaddingPx <= 0) {
-lineWidthPx
} else {
startPaddingPx
}
val bottomPadding = if (endPaddingPx <= 0) {
lineWidthPx
} else {
-endPaddingPx
}
val params = child
.layoutParams as RecyclerView.LayoutParams
val top = child.top - params.topMargin + topPadding
val bottom = child.bottom + params.bottomMargin + bottomPadding
val right = child.left - params.leftMargin
val left = right - lineWidthPx
mPaint.color = color
c.drawRect(left.toFloat(), top.toFloat(), right.toFloat(), bottom.toFloat(), mPaint)
}
private fun drawChildRightVertical(child: View, c: Canvas, @ColorInt color: Int, lineWidthPx: Int, startPaddingPx: Int, endPaddingPx: Int) {
val topPadding = if (startPaddingPx <= 0) {
-lineWidthPx
} else {
startPaddingPx
}
val bottomPadding = if (endPaddingPx <= 0) {
lineWidthPx
} else {
-endPaddingPx
}
val params = child
.layoutParams as RecyclerView.LayoutParams
val top = child.top - params.topMargin + topPadding
val bottom = child.bottom + params.bottomMargin + bottomPadding
val left = child.right + params.rightMargin
val right = left + lineWidthPx
mPaint.color = color
c.drawRect(left.toFloat(), top.toFloat(), right.toFloat(), bottom.toFloat(), mPaint)
}
override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
val itemPosition = (view.layoutParams as RecyclerView.LayoutParams).viewLayoutPosition
val divider = getDivider(itemPosition)
val left = divider.leftSideLine?.widthPx ?: 0
val top = divider.topSideLine?.widthPx ?: 0
val right = divider.rightSideLine?.widthPx ?: 0
val bottom = divider.bottomSideLine?.widthPx ?: 0
outRect.set(left, top, right, bottom)
}
}
Divider类
class Divider(var leftSideLine: SideLine?, var topSideLine: SideLine?, var rightSideLine: SideLine?, var bottomSideLine: SideLine?) {
class Builder {
var leftSideLine: SideLine? = null
var topSideLine: SideLine? = null
var rightSideLine: SideLine? = null
var bottomSideLine: SideLine? = null
fun setLeftSideLine(leftSideLine: SideLine): Builder {
this.leftSideLine = leftSideLine
return this
}
fun setTopSideLine(topSideLine: SideLine): Builder {
this.topSideLine = topSideLine
return this
}
fun setRightSideLine(rightSideLine: SideLine): Builder {
this.rightSideLine = rightSideLine
return this
}
fun setBottomSideLine(bottomSideLine: SideLine): Builder {
this.bottomSideLine = bottomSideLine
return this
}
fun builder(): Divider {
return Divider(leftSideLine, topSideLine, rightSideLine, bottomSideLine)
}
}
}
SideLine类
class SideLine constructor(@ColorInt var color: Int, var widthPx: Int, var startPaddingPx: Int = 0, var endPaddingPx: Int = 0) {
constructor(@ColorInt color: Int, widthPx: Int) : this(color, widthPx, 0, 0)
}