本文已同步发表于我的
微信公众号
,搜索代码说
即可关注,欢迎与我沟通交流。
背景
假设要实现下面的效果图:
![](https://img-blog.csdnimg.cn/5b41bf6171094d9d8b6a7bb39603eaab.png)
如图所示,首先这是一个多样式的滑动列表(截图里只列举了其中的3
种样式),整体外部使用 RecyclerView
来实现没什么疑问。那么截图第3个ItemView
中箭头指向的横向标签列表如何实现呢?
实现思路
我们对上述问题进行一个抽象,本质上就是两个列表:外部是纵向列表,内部有一个横向列表。如下:
![](https://img-blog.csdnimg.cn/63df1b88e2114e93970c158b0e53eda4.png)
外部纵向列表关键代码实现如下:
//RecyclerView.Adapter
open class BaseAdapter<T : Any>(private val vhFactory: IVHFactory) :
RecyclerView.Adapter<BaseVHolder<T>>() {
private val models = mutableListOf<T>()
override fun getItemViewType(position: Int): Int {
val model = models[position]
if (model is IMultiType) return model.getItemViewType()
return super.getItemViewType(position)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseVHolder<T> {
//在这里创建ViewHolder
return vhFactory.getVH(parent.context, parent, viewType) as BaseVHolder<T>
}
override fun onBindViewHolder(holder: BaseVHolder<T>, position: Int) {
//在这里绑定数据
holder.onBindViewHolder(models[position], position)
}
override fun getItemCount(): Int = models.size
fun submitList(newList: List<T>) {
//传入新旧数据进行比对
val diffUtil = ChatDiffUtil(models, newList)
//经过比对得到差异结果
val diffResult = DiffUtil.calculateDiff(diffUtil)
//NOTE:注意这里要重新设置Adapter中的数据
models.clear()
models.addAll(newList)
//将数据传给adapter,最终通过adapter.notifyItemXXX更新数据
diffResult.dispatchUpdatesTo(this)
}
}
//工厂模式,用于生产BaseVHolder
interface IVHFactory {
fun getVH(context: Context, parent: ViewGroup, viewType: Int): BaseVHolder<*>
}
onCreateViewHolder()
用于创建ViewHolder
对象。它会在每次需要一个新的ItemView
时被调用,并返回一个包含了ItemView
的ViewHolder
对象。onBindViewHolder()
则负责将数据与指定位置上的ItemView视图
进行关联,在滚动列表时会多次调用此函数来更新显示内容。
class ChatVHolderFactory : IVHFactory {