【问题标题】:Android- Check multiple items and delete from list of RecyclerViewAndroid-检查多个项目并从 RecyclerView 列表中删除
【发布时间】:2021-12-24 04:00:19
【问题描述】:

我正在尝试检查RecyclerView 中的多个项目并删除它们,但在自定义RecyclerViewAdapter 中检查CheckBox 后无法删除。

class TestAdapter(var isSelectingEnabled: Boolean) : RecyclerViewBaseAdapter<TestModel>() {

 val selectedList: ArrayList<TestModel>? = null
override fun getLayoutResId(viewType: Int): Int = R.layout.test_list_item
var onItemClick: ((TestModel) -> Unit)? = null

override fun bindData(
    holder: SimpleViewHolder<TestModel>,
    model: TestModel,
    position: Int
) {
    val context = holder.itemView.context
    val checkBox = holder.itemView.findViewById<MaterialCheckBox>(R.id.checkbox)
    holder.itemView.setOnClickListener {
        onItemClick?.invoke(model)
    }

    checkBox.apply {
        checkBox.setOnCheckedChangeListener(null)
        checkBox.isChecked = model.isSelected
        isVisible = isSelectingEnabled

        setOnCheckedChangeListener { buttonView, isChecked ->
            selectedList?.add(model)
        }
    }

  }
} 

在片段中:

private fun removeListItems() {
    if (!testAdapter.isSelectingEnabled) {
        testAdapter.removeAllItems(arrayList)
        arrayList.clear()
        binding.buttonBulkAddRemove.isEnabled = false
    } else {
        if (arrayList.size > 0) {
            testAdapter.selectedList?.forEach {
                if (arrayList.contains(it)) {
                    testAdapter.removeItems(it)
                    arrayList.remove(it)
                }
            }
        }
    }
}

BaseAdapter 类中定义了几个方法:

fun removeItems(model: T): Boolean {
    val index = dataList.indexOf(model)
    val removed = dataList.remove(model)
    if (removed) {
        notifyItemRemoved(index)
    }
    return removed
}

fun removeAllItems(listItems: List<T>) {
    dataList.removeAll(listItems)
    notifyDataSetChanged()
}

如果我做错了什么,请指导我。

【问题讨论】:

    标签: android kotlin android-recyclerview


    【解决方案1】:

    您的selectedList 为空。你应该使用val selectedList = mutableListOf&lt;TestModel&gt;()

    此外,您可能希望在未选中项目时从列表中删除它们。

    但是,在我看来,您应该改变策略。这个selectedList 很难与你的 UI 状态保持同步,尤其是在屏幕旋转之后。相反,您可以简单地迭代适配器的源列表并删除 isSelected 的项目。然后将更改通知适配器。

    我猜该列表在您未显示的基本适配器类中。使用重复的notifyRangeRemoved 调用会有点复杂,或者您可以使用notifyDataSetChanged() 并遭受列表的丑陋刷新。如果您使用 ListAdapter 作为基类会更容易。


    编辑,基于更新的问题:

    快速而肮脏的解决方案:从适配器中删除 selectedItems 以及与之交互的所有代码。将这样的函数添加到 TestAdapter 并在您的 Fragment 中使用它:

    fun removeAllCheckedItems() {
        dataList.filter { it.isSelected }
            .forEach { removeItems(it) }
    }
    

    更改您的检查更改侦听器以实际更新您的模型项。无论如何,您都需要这样做,否则当他们滚出屏幕并返回时,它们会显示错误的复选框状态。

    setOnCheckedChangeListener { buttonView, isChecked ->
        model.isChecked = isChecked
    }
    

    但是,我建议使用只读列表、不可变模型类和 ListAdapter 以获得更简洁、更健壮的代码。但这涉及到更多的改变,而且这里的答案太多了。您可以通过网络搜索有关这些主题的文章来了解这些主题。

    【讨论】:

    • 是的,你完全理解了这个要求,如果你能告诉我如何从适配器通知片段会很好。
    • 查看我重写的答案。关于如何在更改列表后刷新 RecyclerView 存在许多问题,但我认为使用 ListAdapter 更好。您可以查找有关此的教程。
    • 用更多代码更新问题,请刷新。它可能会清除你的一切。在这里,我能够成功使用“removeAllItems”,但仅面临选定项目的问题。我无法针对一种情况更新完整的基本适配器。
    • 我在答案中添加了更新。
    • 感谢您的建议。最后我在不更新现有适配器的情况下实现了所有场景:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-23
    • 1970-01-01
    • 1970-01-01
    • 2014-07-30
    • 1970-01-01
    • 2021-12-08
    • 1970-01-01
    相关资源
    最近更新 更多