MyAdapter
自定义可复用ViewAdapter,在前一篇博客里,不多说了。下面是MyAdapter的代码,T
就是list里面装的数据的type
//T: The list data type
abstract class MyViewAdapter<T>(diffCallback: DiffUtil.ItemCallback<T>)
: ListAdapter<T, MyViewHolder<T>>(diffCallback){
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder<T> {
val layoutInflater = LayoutInflater.from(parent.context)
val binding = DataBindingUtil
.inflate<ViewDataBinding>(layoutInflater, viewType, parent, false)
return MyViewHolder(binding)
}
override fun onBindViewHolder(holder: MyViewHolder<T>, position: Int) {
holder.bind(getItem(position))
onClick(holder, tracker)
}
class MyViewHolder<T>(val binding: ViewDataBinding)
: RecyclerView.ViewHolder(binding.root){
fun bind(item: T){
binding.setVariable(BR.item, item)
binding.executePendingBindings()
}
}
}
RecyclerView-Selection
这是一个lib
,详情参照官方文档Enable list-item selection,或者这一篇文章A guide to recyclerview-selection。如果已经学会了使用这个lib
,就往下看,你会看得懂这样的代码,其实就在Adapter
里放了一个Tracker
。Tracker
的初始化略,但要注意一点,必须先初始化RecyclerView
,然后RecyclerView
的 Adapter
,最后才是Tracker
。Aapter
初始化必须在Tracker
之前,Tracker
初始化会用到RecyclerView
,在其内部代码中RecyclerView
会引用它的Adapter
,作为初始化参数,这个时候如果Adapter
为空就会Error
abstract class MyViewAdapter<T>(diffCallback: DiffUtil.ItemCallback<T>)
: ListAdapter<T, MyViewHolder<T>>(diffCallback){
var tracker: SelectionTracker<Long>? = null
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder<T> {
val layoutInflater = LayoutInflater.from(parent.context)
val binding = DataBindingUtil
.inflate<ViewDataBinding>(layoutInflater, viewType, parent, false)
return MyViewHolder(binding)
}
override fun onBindViewHolder(holder: MyViewHolder<T>, position: Int) {
holder.bind(getItem(position))
}
}
这个lib
,通过tracker
来记录你在recyclerView
中选择的item
。有单选和多选两种模式,但是要开启选择必须要长按,才能触发selection。所以如果要避开长按,那么就得手动调用tracker
的select方法。也就是说,要监听RecyclerView
里面的点击事件。
监听RecyclerView里Item的点击事件
由于MyAdapter
抽象类,我并不想只让MyAdapter
完成一种点击事件的处理。所以,我在MyAdapter里面写了一个抽象方法onClick(holder: MyViewHolder<T>)
override fun onBindViewHolder(holder: MyViewHolder<T>, position: Int) {
holder.bind(getItem(position))
holder.binding.root.setOnClickListener {
onClick()
}
}
abstract fun onClick()
实现的一小段代码,就可以在这个Adapter里自定义逻辑了
class AvatarAdapter: MyViewAdapter<String>(DiffCallBack()){
......
override fun onClick() {
}
......
}
当然上面是无法对当前点击的位置的view
进行操作的,因为没有传参数
于是,改进
override fun onBindViewHolder(holder: MyViewHolder<T>, position: Int) {
holder.bind(getItem(position))
holder.binding.root.setOnClickListener {
onClick(holder)
}
}
abstract fun onClick(holder: MyViewHolder<T>)
这样之后,就可以通过获取Binding
对view进行操作了,设置isChecked
,visible
,text
等等
class AvatarAdapter: MyViewAdapter<String>(DiffCallBack()){
......
override fun onClick(holder: MyViewHolder<T>) {
holder.binding.xxxx
}
......
}
手动select
将之前的onClick()小改一下
abstract fun onClick(holder: MyViewHolder<T>, tracker: SelectionTracker<Long>?)
实现,被点击的时候,调用select
方法,传入Key
。这里的Key
就是holder.itemId
。这样就手动将被点击的item放到selection
里面了
class AvatarAdapter: MyViewAdapter<String>(DiffCallBack()){
......
override fun onClick(holder: MyViewHolder<String>, tracker: SelectionTracker<Long>?) {
tracker?.select(holder.itemId)
}
......
}