天天看點

頭部吸頂布局的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
    }

}))
           

繼續閱讀