What\'s the best and easiest way to decorate RecyclerView to have such look & feel?
If you have header use this.
To hide the divider of header set skipHeaderDivider=false, otherwise set true.
class GridDividerItemDecoration : ItemDecoration() {
var skipHeaderDivider = true
private var divider: Drawable? = null
private val bounds = Rect()
private var spacing = 0
fun setDrawable(drawable: Drawable) {
divider = drawable
divider?.intrinsicHeight?.let { spacing = it }
}
override fun onDraw(canvas: Canvas, parent: RecyclerView, state: RecyclerView.State) {
canvas.save()
val childCount = parent.childCount
for (i in 0 until childCount) {
val child = parent.getChildAt(i)
parent.layoutManager?.getDecoratedBoundsWithMargins(child, bounds)
val right: Int = bounds.right + child.translationX.roundToInt()
val left: Int = bounds.left - child.translationX.roundToInt()
val bottom: Int = bounds.bottom + child.translationY.roundToInt()
val top: Int = bounds.top - child.translationY.roundToInt()
divider?.setBounds(left, top, right, bottom)
divider?.draw(canvas)
}
canvas.restore()
}
override fun getItemOffsets(
outRect: Rect,
view: View,
parent: RecyclerView,
state: RecyclerView.State
) {
val gridLayoutManager = parent.layoutManager as? GridLayoutManager ?: return
val position = gridLayoutManager.getPosition(view)
if (position < 0) return
val spanCount = gridLayoutManager.spanCount
val positionalSpanSize = gridLayoutManager.spanSizeLookup.getSpanSize(position)
if (skipHeaderDivider && positionalSpanSize == spanCount) return
val itemCount = gridLayoutManager.itemCount
val onBottom = position >= itemCount - spanCount
var nextHeader = false
run loop@{
for (i in 1..spanCount) {
val nextSpanSize = gridLayoutManager.spanSizeLookup.getSpanSize(position + i)
if (nextSpanSize == spanCount) {
nextHeader = true
return@loop
}
}
}
outRect.top = spacing
outRect.left = 0
outRect.right = spacing
outRect.bottom = if (nextHeader || onBottom) spacing else 0
}
}