目录
ListAdapter封装(三)- 头尾,多类型,嵌套,单多选
前言
上一篇文章已经讲解 SimpleAdapter 的基本封装. 这次我们将用 ConcatAdapter 封装头尾;
并封装多类型Adapter, 嵌套Adapter, 单多选Adapter;
Paging3 中, PagingDataAdapter 的封装方式也可以参考本篇
推荐文章
- ListAdapter封装, 告别Adapter代码 (一)- ListAdapter 入门
- ListAdapter封装, 告别Adapter代码 (二)- SimpleAdapter
- ListAdapter封装, 告别Adapter代码 (三)- 头尾,多类型,嵌套,单多选
- paging3-分页数据加载库(入门)
提示:以下是本篇文章正文内容,下面案例可供参考
一、用 ConcatAdapter 封装头尾;
1.ConcatAdapter 简介
ConcatAdapter 是 recyclerview: 1.2.0-alpha 04 中提供的一个新组件;
它可以帮我们顺序地组合多个 Adapter,并让它们显示在同一个 RecyclerView 中。
想了解小伙伴 点这里
先导包, 需要 recyclerview 1.2.0
recyclerview = '1.2.0'
implementation androidx.recyclerview:recyclerview:${recyclerview}
2.思路
以前我们头尾是单独的 ViewType; 现在呢,它们变成了单独的 Adapter; 所以, 现在要创建 单条目的Adapter
- EndAdapter: 固定一个条目, 也不需要绑定数据, View由Activity或Fragment控制;
- EndHolder: 继承 ViewHolder, 传递View即可
/**
* 头尾 Adapter; View由外部 维护;
*/
class EndAdapter(val view: View) : RecyclerView.Adapter<EndHolder>(){
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = EndHolder(view)
override fun onBindViewHolder(holder: EndHolder, position: Int) {}
override fun getItemCount() = 1
}
class EndHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
3.在BaseAdapter中加入 withHeaderAndFooter()
两个View参数 header, footer; 创建 EndAdapter 并最终返回组装后的 ConcatAdapter 对象
/**
* 组装头尾, 返回一个新的 ConcatAdapter 实体, 需要将新实体设置给 RecycleView
*/
fun withHeaderAndFooter(
header: View? = null,
footer: View? = null
) = when{
header != null && footer != null -> ConcatAdapter(EndAdapter(header), this, EndAdapter(footer))
header != null && footer == null -> ConcatAdapter(EndAdapter(header), this)
header == null && footer != null -> ConcatAdapter(this, EndAdapter(footer))
else -> this
}
下面是 Activity代码, 只需要将 withHeaderAndFooter() 返回的 Adapter 赋给 RecycleView即可. 我们操作数据还是用 主 mAdapter
val headBinding = ViewHeaderTjBinding.inflate(LayoutInflater.from(mActivity), mView as @Nullable ViewGroup, false)
//主数据 Adapter
mAdapter = MultipleAdapter()
//将这个由 withHeaderAndFooter() 返回的 ConcatAdapter 赋给 RecycleView 即可
val cAdapter = mAdapter.withHeaderAndFooter(headBinding.root)
mDataBind.rvRecycle.let {
it.layoutManager = LinearLayoutManager(mActivity)
it.adapter = cAdapter
}
4. BaseAdapter 最终代码
在 BaseAdapter 中加入方便本地操作的 增删改 方法; 最终代码如下
abstract class BaseAdapter<T: BaseItem>(
protected val handler: BaseHandler? = null) :
ListAdapter<T, NewViewHolder>(DiffCallback()) {
override fun onBindViewHolder(holder: NewViewHolder, position: Int) {
holder.bind(getItem(position))
}
/**
* 重写 提交数据方法, 让它必定以新数据集合对象传入
*/
override fun submitList(list: MutableList<out T>?) {
val newData = mutableListOf<T>()
if(list != null){
newData.addAll(list)
}
super.submitList(newData)
}
/**
* 删除指定条目
*/
fun remove(entity: BaseItem){
removeAt(currentList.indexOf(entity))
}
fun removeAt(position: Int){
if(position == -1) return
if(position >= currentList.size) return
val newData = mutableListOf<T>()
newData.addAll(currentList)
newData.removeAt(position)
super.submitList(newData)
}
/**
* 修改指定条目
*/
fun update(entity: T){
updateAt(currentList.indexOf(entity))
}
fun updateAt(position: Int){
if(position == -1) return
if(position >= currentList.size) return
notifyItemChanged(position)
}
/**
* 新增条目
*/
fun insert(entity: T, position: Int = -1){
val newData = mutableListOf<T>()
newData.addAll(currentList)
if(position < newData.size && position >= 0){
newData.add(position, entity)
}else{
newData.add(entity)
}
super.submitList(newData)
}
/**
* 组装头尾, 返回一个新的 ConcatAdapter 实体, 需要将新实体设置给 RecycleView
*/
fun withHeaderAndFooter(
header: View? = null,
footer: View? = null
) = when{
header != null && footer != null -> ConcatAdapter(EndAdapter(header), this, EndAdapter(footer))
header != null && footer == null -> ConcatAdapter(EndAdapter(header), this)
header == null && footer != null -> ConcatAdapter(this, EndAdapter(footer))
else -> this
}
}
二、多条目类型 MultipleAdapter
多类型超简单的, 还是重写 getItemViewType();
有区别的是, getItemViewType() 的返回值, 直接返回 布局文件ID. 然后实体类自行判断给出 LayoutId
1.实体类
还是实现 BaseItem, 重写 getMItemType() , 返回布局文件 ID
class MultipleEntity(
var name: String,
var index: Int = 0,
override var hasChanged: Boolean = false)
: BaseItem {
/**
* 实体类自行判断, 并给出 布局id
*/
override fun getMItemType(): Int {
return if(index % 2 == 0){
R.layout.item_multiple_one
}else{
R.layout.item_multiple_two
}
}
}
2.MultipleAdapter
需要重写 getItemViewType() 并将实体类的 getMItemType() 结果返回;
创建 ViewHolder 的时候, 直接用 viewType 作为布局ID (因为我们用布局ID做的ViewType)
/**
* 多条目 类型 Adapter;
* 1.实体类需要重写 {@link BaseItem} 的 getMItemType() 方法; 并根据类型,返回不同的 LayoutId
* 2.复杂 Adapter. 还需要自定义; 继承 MultipleAdapter 并重写 getItemViewType()
*/
open class MultipleAdapter(handler: BaseHandler? = null) :
BaseAdapter<BaseItem>(handler) {
/**
* Item类型, 同 layoutId;
*/
override fun getItemViewType(position: Int): Int {
return currentList[position].getMItemType()
}
/**
* viewType 同 layoutId
*/
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NewViewHolder {
if(viewType == 0) throw RuntimeException("Undefined itemViewType")
return NewViewHolder(
DataBindingUtil.inflate(
LayoutInflater.from(parent.context),
viewType, parent, false
), handler
)
}
}
3.开始使用
接下来就是用了; 如下
mAdapter = MultipleAdapter()
mDataBind.rvRecycle.let {
it.layoutManager = LinearLayoutManager(mActivity)
it.adapter = mAdapter
}
val data = mutableListOf<MultipleEntity>()
repeat(30){
if(it % 2 == 0){
data.add(MultipleEntity("小美", it))
}else{
data.add(MultipleEntity("小状", it))
}
}
mAdapter.submitList(data)
很简单是不是, 直接把数据集合塞进Adapter里 就完事了
布局文件也帖出来吧, 如下:
item_multiple_one.xml
<layout>
<data>
<variable
name="item"
type="com.example.kotlinmvpframe.yiyou.entity.MultipleEntity" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:padding="12dp">
<TextView
style="@style/tv_base_16_dark"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text='@{item.name + " 我是类型one,我有靓照"}'
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
<ImageView
style="@style/img_wrap"
android:layout_width="60dp"
android:layout_height="50dp"
android:src="@drawable/bg"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
item_multiple_two.xml
<layout>
<data>
<variable
name="item"
type="com.example.kotlinmvpframe.yiyou.entity.MultipleEntity" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:padding="12dp">
<TextView
style="@style/tv_base_16_dark"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text='@{item.name + " 我是类型two,我有money"}'
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
<TextView
style="@style/tv_base_16_dark"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="italic|bold"
android:textColor="@color/shape_red"
android:text="¥. 500"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
效果图:
三、嵌套 NestedAdapter
嵌套就是指 RecycleView 套 RecycleView
一般在外层实体中; 例如 一条朋友圈中多张图片. 外层实体持有 Image集合;
思路:
- 子层数据集合: 我们就用接口的方式, 规范这个集合
- 子层RecycleView:
我们的Holder是用的 ViewDataBinding 对象, 而不是确定的View. 怎么拿子层的的 RecycleVIew 呢? 我们规范 嵌套子层 RecycleView 的ID, 用 findViewById 的方式 把它存到 ViewHolder 里;
- 子层的 Adapter: 这个好办, 上一篇我们已经封装好了 SimpleAdapter;
- 子层列表事件: 子层的事件, 还是用 handler 处理, 但最终由回调函数,调到主界面处理;
1.实体类
BaseNestedItem 嵌套类型数据实体基类
interface BaseNestedItem : BaseItem{
fun getNestedList(): MutableList<out BaseItem>?
}
MultipleEntity
class MultipleEntity(
var name: String,
override var hasChanged: Boolean = false)
: BaseNestedItem {
var imgs: MutableList<ImageEntity>? = null
// 返回子层集合
override fun getNestedList(): MutableList<ImageEntity>? = imgs
/**
* 子层集合实体类
*/
class ImageEntity(val res: Int, override var hasChanged: Boolean = false) : BaseItem
}
2.NestedAdapter
直接上代码
/**
* 单条目, 简单Item MVVM Adapter
* 复杂类型 还是得自定义 Adapter
*/
open class NestedAdapter<T : BaseNestedItem>(
/**
* 外层列表 item布局;
*/
private val layout: Int,
/**
* 内层列表 item布局;
*/
private val nestedLayoutId: Int,
/**
* 生成子层Recycle的 LayoutManager; 可以是 LinearLayoutManager GridLayoutManager 等;
* 默认 横向 LinearLayoutManager
*/
private val childLayoutManager: (() -> RecyclerView.LayoutManager)? = null,
/**
* 子层列表点击回调; 此方式可能不太优雅. 有待改进
* arg1 子层点击 View
* arg2 外层点击 position; 这个position并不保险; 当存在 Header 时, 它需要 -1
* arg3 子层实体对象
*/
private val childClickListener: ((View, Int, BaseItem) -> Unit)? = null,
/**
* 外层类表点击事件;
*/
handler: BaseHandler? = null
) :
BaseAdapter<T>(handler) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NewViewHolder {
val bingding: ViewDataBinding = DataBindingUtil.inflate(LayoutInflater.from(parent.context), layout, parent, false)
// 统一规范 子层 RecycleView 的id; 将 RecyclerView 存入 NestedHolder
val rvNested = bingding.root.findViewById<RecyclerView>(R.id.rv_nested_item)
return NestedHolder(rvNested, bingding, handler)
}
override fun onBindViewHolder(holder: NewViewHolder, position: Int) {
if(holder is NestedHolder){
//绑定子层 Recycle Adapter
createNestedAdapter(holder)
//绑定子层 数据
(holder.rvNested?.adapter as SimpleAdapter?)?.submitList(getItem(position).getNestedList())
}
super.onBindViewHolder(holder, position)
}
/**
* 绑定子层 Recycle 的 Adapter
*/
private fun createNestedAdapter(holder: NestedHolder) {
holder.rvNested?.let {
if(it.adapter == null){
//子层点击事件; null 则不设置;
val handler = if(childClickListener == null){
null
}else{
object : Handler<BaseItem>(){
override fun onClick(view: View, info: BaseItem) {
childClickListener.invoke(view, holder.layoutPosition, info)
}
}
}
val adapter = SimpleAdapter(nestedLayoutId, handler)
it.layoutManager = childLayoutManager?.invoke() ?: LinearLayoutManager(it.context, RecyclerView.HORIZONTAL, false)
it.adapter = adapter
}
}
}
/**
* 重写 ViewHoleder, 附带 RecyclerView
*/
class NestedHolder(val rvNested: RecyclerView?, binding: ViewDataBinding, handler: BaseHandler?) : NewViewHolder(binding, handler)
}
讲解:
可以看出, NestedAdapter 的内外层布局 ID直接传入;
内层 LayoutManager, 及事件响应 由kotlin高阶函数提供;
注意: 内层事件响应时, 回调给了外层position 是通过 holder.layoutPosition; 但是在有头部的Adapter中 layoutPosition 是需要减1的; 还有一个 holder.bindingAdapterPosition 参数, 但是它在 带头部的ConcatAdapter 中使用时, 经常返回 -1; 不知道是不是博主使用姿势不对;
3.开始使用
mAdapter = NestedAdapter<MultipleEntity>(
//主列表布局 ID
R.layout.item_nested_one,
//子列表布局 ID
R.layout.item_img,
//事件响应
childClickListener = {
_, layoutPosition, info ->
val childIndex = (mAdapter.currentList[layoutPosition] as MultipleEntity).imgs?.indexOf(info) ?: 0
Toast.makeText(mActivity.applicationContext, "点击了第${layoutPosition + 1} 的第${childIndex + 1}个条目", Toast.LENGTH_SHORT).show()
})
mDataBind.rvRecycle.let {
it.layoutManager = LinearLayoutManager(mActivity)
it.adapter = mAdapter
}
val data = mutableListOf<MultipleEntity>()
repeat(5){
val entity = if(it % 2 == 0){
MultipleEntity("小美", it)
}else{
MultipleEntity("小状", it)
}
entity.imgs = mutableListOf(
ImageEntity(R.drawable.bg), ImageEntity(R.drawable.bg), ImageEntity(R.drawable.bg), ImageEntity(R.drawable.bg),
ImageEntity(R.drawable.bg), ImageEntity(R.drawable.bg), ImageEntity(R.drawable.bg), ImageEntity(R.drawable.bg))
data.add(entity)
}
mAdapter.submitList(data)
布局贴出来
item_nested_one.xml
<layout>
<data>
<variable
name="item"
type="com.example.kotlinmvpframe.yiyou.entity.MultipleEntity" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:padding="12dp">
<TextView
android:id="@+id/tv_name_item"
style="@style/tv_base_16_dark"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text='@{item.name}'
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_nested_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
app:layout_constraintTop_toBottomOf="@id/tv_name_item"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
item_img.xml
<layout>
<data>
<variable
name="item"
type="com.example.kotlinmvpframe.yiyou.entity.MultipleEntity.ImageEntity" />
<variable
name="handler"
type="com.example.kotlinmvpframe.test.testtwo.Handler" />
</data>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{v -> handler.onClick(v, item)}"
android:padding="8dp">
<ImageView
style="@style/img_wrap"
android:layout_width="80dp"
android:layout_height="80dp"
app:imgRes="@{item.res}"/>
</FrameLayout>
</layout>
效果图来了:
四、单选 SingleChoiceAdapter
单项勾选; 怎么做? 选中的条目要有标记, 前一个选中的条目要反选等
分析:
实体需要有 checked 字段, 我们用 BaseCheckedItem 作为实体基类
规范 布局文件中 CheckBox 的 ID, onCreateViewHolder 时 通过 findViewById 将控件保存到 ViewHolder
选中某个条目时, 之前选中的条目需要反选. 所以必须要知道上一次选中的谁
监听 onCheckedChanged 事件, 新实体选中, 旧实体反选.
单选时, 不允许反选, 此时不用 CheckBox, 而用 RadioButton
1. 实体类写法
BaseCheckedItem
/**
* 普通单多选列表 实体类
*/
interface BaseCheckedItem : BaseItem{
var hasChecked: Boolean // 是否被勾选中
}
CheckEntity
class CheckEntity(
var name: String? = null,
override var hasChecked: Boolean = false,
override var hasChanged: Boolean = false)
: BaseCheckedItem
2.Adapter
直接上代码吧, 已经写了注释
class SingleChoiceAdapter<T : BaseCheckedItem>(
/**
* 布局id;
*/
private val layout: Int,
handler: BaseHandler? = null
): BaseAdapter<T>(handler), CompoundButton.OnCheckedChangeListener {
//弱引用, 当选中条目被删除时, 应当释放资源
var wearEntity: WeakReference<T>? = null
var wearView: WeakReference<CompoundButton>? = null
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NewViewHolder {
val bingding: ViewDataBinding = DataBindingUtil.inflate(LayoutInflater.from(parent.context), layout, parent, false)
// 统一规范 CheckBox 的id; 将 RecyclerView 存入 ChoiceHolder
val cbCheck = bingding.root.findViewById<CompoundButton>(R.id.cb_check_item)
return ChoiceHolder(cbCheck, bingding, handler)
}
override fun onBindViewHolder(holder: NewViewHolder, position: Int) {
if(holder is ChoiceHolder){
val entity = currentList[position]
if(entity.hasChecked){
wearEntity = WeakReference(entity)
wearView = WeakReference(holder.cbCheck)
}
//用 tag 将对象实体存储;
holder.cbCheck?.tag = entity
holder.cbCheck?.setOnCheckedChangeListener(this)
//这一行是测试用的, 应当删掉
(entity as CheckEntity).name = Integer.toHexString(holder.cbCheck?.hashCode() ?: 0)
}
super.onBindViewHolder(holder, position)
}
/**
* checkbox 选中事件
*/
override fun onCheckedChanged(buttonView: CompoundButton?, isChecked: Boolean) {
//判断是否是 手动操作
if(buttonView?.isPressed == true){
Log.d("pppppppppppppppppp", "手动操作了 ChekcBox")
wearEntity?.let {
it.get()?.hasChecked = false
it.clear()
}
// 因 RecycleView 复用机制, 这里新旧 Button 可能为同一个;
// 当同一个button 时, 不需要重置原button 的选中状态; 不需要重新 new WeakReference
val isSameBtn = buttonView == wearView?.get()
if(!isSameBtn){
wearView?.let {
it.get()?.isChecked = false
it.clear()
}
wearView = WeakReference(buttonView)
}
val entity = buttonView.tag as T?
entity?.hasChecked = true
wearEntity = WeakReference(entity)
}
}
/**
* 重写 ViewHoleder, 附带 ImageView; 勾选是使用 ImageView 切换图片的方式
*/
class ChoiceHolder(val cbCheck: CompoundButton?, binding: ViewDataBinding, handler: BaseHandler?) : NewViewHolder(binding, handler)
}
3.开始使用
很简单, 只需要 初始化 Adapter, RecycleView; 并设置数据源即可
mAdapter = SingleChoiceAdapter(R.layout.item_test_choise)
mDataBind.rvRecycle.let {
it.layoutManager = LinearLayoutManager(mActivity)
it.adapter = mAdapter
}
val data = mutableListOf<CheckEntity>()
repeat(15){
data.add(CheckEntity("小华"))
}
mAdapter.submitList(data)
//以下, 获取选中项
mDataBind.btnLeft.setOnClickListener {
val entity = mAdapter.wearEntity?.get()
if(entity == null){
Toast.makeText(mActivity, "当前未选中", Toast.LENGTH_SHORT).show()
return@setOnClickListener
}
val position = mAdapter.currentList.indexOf(entity)
Toast.makeText(mActivity, "当前选中${entity.name}, index=${position}", Toast.LENGTH_SHORT).show()
}
mDataBind.btnRight.setOnClickListener {
mAdapter.notifyDataSetChanged()
}
布局贴出来
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="item"
type="com.example.kotlinmvpframe.yiyou.entity.CheckEntity" />
<variable
name="handler"
type="com.example.kotlinmvpframe.test.testtwo.Handler" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:text="@{item.name}"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
<RadioButton
android:id="@+id/cb_check_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableEnd="@drawable/checkbox_selector"
android:padding="24dp"
android:background="@null"
android:button="@null"
android:checked="@{item.hasChecked}"
app:layout_constraintTop_toTopOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
效果图:
五、多选 MultipleChoiceAdapter
多选就简单了; 它不需要知道上一次选中的是谁.
注意, 需要将 item_test_choise 中的 RadioButton 换成 CheckBox
好, 上代码
class MultipleChoiceAdapter<T : BaseCheckedItem>(
/**
* 布局id;
*/
private val layout: Int,
handler: BaseHandler? = null
): BaseAdapter<T>(handler), CompoundButton.OnCheckedChangeListener {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NewViewHolder {
val bingding: ViewDataBinding = DataBindingUtil.inflate(LayoutInflater.from(parent.context), layout, parent, false)
// 统一规范 CheckBox 的id; 将 RecyclerView 存入 NestedHolder
val cbCheck = bingding.root.findViewById<CompoundButton>(R.id.cb_check_item)
return SingleChoiceAdapter.ChoiceHolder(cbCheck, bingding, handler)
}
override fun onBindViewHolder(holder: NewViewHolder, position: Int) {
if(holder is SingleChoiceAdapter.ChoiceHolder){
val entity = currentList[position]
holder.cbCheck?.tag = entity
holder.cbCheck?.setOnCheckedChangeListener(this)
}
super.onBindViewHolder(holder, position)
}
/**
* checkbox 选中事件
*/
override fun onCheckedChanged(buttonView: CompoundButton?, isChecked: Boolean) {
//判断是否是 手动操作
if(buttonView?.isPressed == true){
val entity = buttonView.tag as T?
entity?.hasChecked = isChecked
}
}
}
使用:
使用跟 单选Adapter一样, 初始化RecycleVIew, 设置数据源即可;
遍历的话这样:
val list = mAdapter.currentList.filter {
it.hasChecked
}
Toast.makeText(mActivity, "当前选中${list.size}条", Toast.LENGTH_SHORT).show()
效果图:
好的! 终于 写完了
总结
好吧, 没有总结
上一篇: ListAdapter封装, 告别Adapter代码 (二)- SimpleAdapter
下一篇: paging3-分页数据加载库(入门)