效果圖

原理
實際上就是繪制一個頭部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
}
}))