仓库地址 https://gitee.com/BigObj/bo-an-poj-common
通过给 RecycleView add ItemDecoration 设置 item 上下左右间距
自定义 RecyclerView.ItemDecoration
重写 getItemOffsets 给间距赋值
重写 onDraw 将 需要填充在间距中的 drawable 绘制出来
模型
class ItemSpace {
/**
* 上间隔填充
*/
var topDrawable: Drawable? = null
/**
* 下间隔填充
*/
var bottomDrawable: Drawable? = null
/**
* 设置item上下左右间隔尺寸
*/
val rect: Rect by lazy {
Rect(0, 0, 0, 0)
}
/**
* 上填充间隔 的 margin
*/
val topDrawableMargin: Rect by lazy {
Rect(0, 0, 0, 0)
}
/**
* 下填充间隔 的 margin
*/
val bottomDrawableMargin: Rect by lazy {
Rect(0, 0, 0, 0)
}
}
实现
class RecyclerItemDecoration(private var spaceArray: SparseArray<ItemSpace>): RecyclerView.ItemDecoration() {
override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
super.onDraw(c, parent, state)
val left = parent.left
val right = parent.right
val childCount = parent.childCount
// 遍历所有展示的 itemView 为其添加上下填充视图
for (i in 0 until childCount) {
val view = parent.getChildAt(i)
val viewHolder = parent.getChildViewHolder(view)
val itemSpace = spaceArray[viewHolder.itemViewType]
// 绘制上间隔填充物
itemSpace?.topDrawable?.setBounds(
left + itemSpace.topDrawableMargin.left + itemSpace.rect.left,
(view.y - itemSpace.rect.top).toInt() + itemSpace.topDrawableMargin.top,
right - itemSpace.topDrawableMargin.right - itemSpace.rect.right,
view.y.toInt() - itemSpace.topDrawableMargin.bottom
)
itemSpace?.topDrawable?.draw(c)
// 绘制下间隔填充物
itemSpace?.bottomDrawable?.setBounds(
left + itemSpace.bottomDrawableMargin.left + itemSpace.rect.left,
(view.y + view.height).toInt() + itemSpace.bottomDrawableMargin.top,
right - itemSpace.bottomDrawableMargin.right - itemSpace.rect.right,
(view.y + view.height).toInt() + itemSpace.rect.bottom - itemSpace.bottomDrawableMargin.bottom
)
itemSpace?.bottomDrawable?.draw(c)
}
}
override fun getItemOffsets(
outRect: Rect,
view: View,
parent: RecyclerView,
state: RecyclerView.State
) {
super.getItemOffsets(outRect, view, parent, state)
val viewHolder = parent.getChildViewHolder(view)
val itemSpace = spaceArray[viewHolder.itemViewType]
itemSpace?.rect?.apply {
outRect.top = top
outRect.bottom = bottom
outRect.left = left
outRect.right = right
}
}
}