天天看点

头部吸顶布局的RecycleView简单实现

效果图

头部吸顶布局的RecycleView简单实现

原理

实际上就是绘制一个头部item在

RecycleView

上显示即可,该Item没有随着滑动变动所以看起来就像一个固定的头部。

实现ItemDecoration,重写其

onDraw

onDrawOver和

getItemOffsets。

//将decoration绘制到canvas上,会优先于itemView进行绘制,所以超出绘制区域会被itemView覆盖,不会有影响(可以理解为绘制背景)
public void onDraw(Canvas c, RecyclerView parent, State state);

//作用同onDraw,但是晚于itemView的绘制,所以会覆盖在recycleView之上,是完整可见的(不超出 RecycleView 的情况下)
public void onDrawOver(Canvas c, RecyclerView parent, State state);

//将这个方法中获取的outRect插到padding或者margin中,扩大了itemView之间的间距,用于onDraw中绘制decoration
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, State state);
           

具体

class StickItemDecoration(var groupInterface: GroupInterface?) : ItemDecoration() {

    private var paint: Paint? = null

    init {
        paint = Paint(Paint.ANTI_ALIAS_FLAG)
        paint?.color = Color.RED
        paint?.style = Paint.Style.FILL
    }

    override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
        val index = parent.getChildAdapterPosition(view)
        groupInterface?.let {
            if(groupInterface!!.isFirst(index)){
                outRect.set(0, 100, 0, 0)
                return
            }
        }

        outRect.set(0, 5, 0, 0)
    }

    override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
        super.onDraw(c, parent, state)

        val childCount = parent.childCount
        for (i in 0 until childCount){
            val view = parent.getChildAt(i)
            val index = parent.getChildAdapterPosition(view)

            if(groupInterface != null && groupInterface!!.isFirst(index)){
                paint?.let {
                    it.color = Color.BLUE
                    c.drawRect(view.left.toFloat(), (view.top - 100).toFloat(), view.right.toFloat(), view.top.toFloat(), it)
                    it.color = Color.GREEN
                    it.textSize = 100f
                    c.drawText(groupInterface!!.getGroupId(index), view.left.toFloat(), view.top.toFloat(), it)
                }
            } else {
                paint?.let {
                    it.color = Color.TRANSPARENT
                    c.drawRect(view.left.toFloat(), (view.top - 5).toFloat(), view.right.toFloat(), view.top.toFloat(), it)
                }
            }
        }
    }

    override fun onDrawOver(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
        super.onDrawOver(c, parent, state)

        val firstVisibleView = parent.getChildAt(0)

        val firstVisbleIndex = parent.getChildAdapterPosition(firstVisibleView)
        val firstVisbleGroupId = groupInterface?.getGroupId(firstVisbleIndex)

        if(firstVisibleView != null && firstVisibleView.top < 100){
            paint?.let {
                it.color = Color.BLUE
                c.drawRect(parent.left.toFloat(), 0f, parent.right.toFloat(), 100f, it)
                it.color = Color.GREEN
                c.drawText(firstVisbleGroupId, parent.left.toFloat(), 100f, it)
            }
        }
    }
}

interface GroupInterface{

    fun isFirst(index: Int): Boolean

    fun getGroupId(index: Int): String
}

data class GroupItem(var content: String, var isFirst: Boolean, var groupId: String)
           

使用

recyclerView.addItemDecoration(StickItemDecoration(object: GroupInterface{

    override fun isFirst(index: Int): Boolean {
        return dataSource.get(index).isFirst
    }

    override fun getGroupId(index: Int): String {
        return dataSource.get(index).groupId
    }

}))
           

继续阅读