Android RecyclerView 吸顶效果
Posted danfengw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android RecyclerView 吸顶效果相关的知识,希望对你有一定的参考价值。
请先阅读Android RecyclerView 吸顶效果(一),推荐参考第一篇文章的方案来实现,这里只是帖一下第二种方案的代码,简单的介绍一下ItemDecoration
实现效果:
ItemDecoration
太懒了,截个图,如有侵权,请告知,会进行删除!
主要代码
StickyItemDecoration
class StickyItemDecoration(val context: Context, val mList: MutableList<Bean> = mutableListOf()) :
RecyclerView.ItemDecoration()
private var paint: Paint? = null
private var textPaint: Paint = Paint()
private var dividerHeight: Float = dp2Px(50).toFloat()
init
paint = Paint()
paint?.setColor(context.resources.getColor(R.color.colorAccent))
paint?.style = Paint.Style.FILL
textPaint?.setColor(context.resources.getColor(R.color.FF333333))
textPaint?.style = Paint.Style.FILL
textPaint?.textSize = sp2Px(14).toFloat()
override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State)
super.getItemOffsets(outRect, view, parent, state)
val position = parent.getChildAdapterPosition(view)
if (isGroupFirst(position))
outRect.top = dividerHeight.toInt()
else
outRect.top = 0
override fun onDraw(canvas: Canvas, parent: RecyclerView, state: RecyclerView.State)
super.onDraw(canvas, parent, state)
val childCount = parent.childCount
for (i in 0 until childCount)
val childView = parent.getChildAt(i)
val childAdapterPos = parent.getChildAdapterPosition(childView)
val groupName = getGroupName(childAdapterPos)
val left = childView.paddingLeft
val right = childView.paddingRight
paint?.let
if (isGroupFirst(childAdapterPos))
val top = childView.top - dividerHeight
val bottom = childView.top.toFloat()
canvas.drawRect(left.toFloat(), top, (childView.width - right).toFloat(), bottom, it)
groupName ?: return
val baseLine = (top + bottom) / 2f - (textPaint.descent() + textPaint.ascent()) / 2f
canvas.drawText(groupName, left + dp2Px(10).toFloat(), baseLine, textPaint)
override fun onDrawOver(canvas: Canvas, parent: RecyclerView, state: RecyclerView.State)
super.onDrawOver(canvas, parent, state)
val firstVisiblePos = (parent.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition()
// 这里必须获取itemView 不能通过parent.getChildAt的方式,原因是getChildAt的方式会出现top准确的情况
val view = parent.findViewHolderForAdapterPosition(firstVisiblePos)?.itemView
view ?: return
val top = parent.paddingTop
val left = parent.paddingLeft
val right = parent.width - view.paddingRight
paint?.let
if (isGroupFirst(firstVisiblePos))
val bottom = Math.min(dividerHeight, view.bottom.toFloat())
canvas.drawRect(left.toFloat(), top + view.top - dividerHeight, right.toFloat(), top + bottom, it)
val baseLine = ((top + bottom) - (textPaint.ascent() + textPaint.descent())) / 2f
canvas.drawText(getGroupName(firstVisiblePos)!!, left + dp2Px(10).toFloat(), baseLine, textPaint)
else
canvas.drawRect(left.toFloat(), top.toFloat(), right.toFloat(), top.toFloat() + dividerHeight, it)
val baseLine = ((top + top + dividerHeight) - (textPaint.ascent() + textPaint.descent())) / 2f
canvas.drawText(getGroupName(firstVisiblePos)!!, left + dp2Px(10).toFloat(), baseLine, textPaint)
private fun getGroupName(position: Int): String?
return mList[position].groupName
private fun isGroupFirst(position: Int): Boolean
return if (position == 0)
true
else
val lastGroupName = mList[position - 1].groupName
val currentGroupName = mList[position].groupName
lastGroupName != currentGroupName
private fun dp2Px(dpValue: Int): Int
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpValue.toFloat(), context.resources.displayMetrics).toInt()
private fun sp2Px(spValue: Int): Int
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, spValue.toFloat(), context.resources.displayMetrics).toInt()
数据
class Bean(val text: String, val groupName: String)
Activity
class SimpleActivity : AppCompatActivity()
private val beanList = mutableListOf<Bean>()
private var recyclerView: RecyclerView? = null
override fun onCreate(savedInstanceState: Bundle?)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_sample_2)
initData()
initRecyclerView()
private fun initRecyclerView()
recyclerView = findViewById(R.id.recyclerView)
recyclerView?.adapter = SampleAdapter2(beanList)
recyclerView?.layoutManager = LinearLayoutManager(this)
recyclerView?.layoutParams?.width = ViewGroup.LayoutParams.MATCH_PARENT
recyclerView?.layoutParams?.height = ViewGroup.LayoutParams.WRAP_CONTENT
recyclerView?.addItemDecoration(StickyItemDecoration(this, beanList))
private fun initData()
for (i in 0..5)
beanList.add(Bean("第一组 $i + 1 号", "第一组"))
for (i in 0..5)
beanList.add(Bean("第二组 $i + 1 号", "第二组"))
for (i in 0..5)
beanList.add(Bean("第三组 $i + 1 号", "第三组"))
for (i in 0..5)
beanList.add(Bean("第四组 $i + 1 号", "第四组"))
for (i in 0..5)
beanList.add(Bean("第五组 $i + 1 号", "第五组"))
Adapter
class SampleAdapter2(var data: MutableList<Bean>? = mutableListOf()) : RecyclerView.Adapter<Holder>()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder
return Holder(LayoutInflater.from(parent.context).inflate(R.layout.item, parent, false))
override fun getItemCount(): Int
return data?.size ?: 0
override fun onBindViewHolder(holder: Holder, position: Int)
holder.bindData(data?.get(position)?.text)
class Holder(view: View) : RecyclerView.ViewHolder(view)
private var textView: TextView? = null
init
textView = view.findViewById(R.id.tv)
fun bindData(s: String?)
s ?: return
textView?.text = s
以上是关于Android RecyclerView 吸顶效果的主要内容,如果未能解决你的问题,请参考以下文章
Android 自定义ItemDecoration-实现分组吸顶效果
RecyclerView 悬浮吸顶效果实现,支持数据绑定及Touch事件
RecyclerView 悬浮吸顶效果实现,支持数据绑定及Touch事件