Decorating RecyclerView (with GridLayoutManager) to display divider between items

后端 未结 9 1484
旧时难觅i
旧时难觅i 2020-12-07 09:44

What\'s the best and easiest way to decorate RecyclerView to have such look & feel?

\"enter

9条回答
  •  臣服心动
    2020-12-07 10:05

    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
        }
    }
    

提交回复
热议问题