如何在回收站视图中正确 select 和 deselect 项目?

How to properly select and deselect items in recycler view?

我是 Android Kotlin 的初学者,我正在开发一个练习应用程序,它需要从回收器视图中选择的数据放在数组列表中。在我更改我的微调器值并重新加载项目之前,选择工作正常,一旦重新加载项目,需要单击两次才能取消选择,但仍未从所选数据 arrayList 中删除。 (每当更改微调器值时,都会从 API 加载数据)。我知道这段代码很乱,有很多不必要的东西,如果有人能帮我清理代码并解决问题,我会很高兴。

class RecyclerViewAdapter(val dataList:ArrayList<ModelClass>):RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder>(){

   object ob {
        val dataSelected= ArrayList<ModelClass>()

   }

private  var _binding: ItemViewBinding? = null
private val binding get() = _binding!!
private lateinit var nListener : onItemClickListener

interface onItemClickListener{
    fun onItemClick(position: Int)

}
fun setOnItemClickListener(listener:onItemClickListener){
    nListener=listener
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerViewAdapter.ViewHolder {

    val v=LayoutInflater.from(parent.context).inflate(R.layout.item_view,parent,false)
    _binding= ItemViewBinding.bind(v)

    return ViewHolder(binding.root)
}
fun bindItems(data:ModelClass){


    binding.itemQuant.text=data.item_quant
    binding.itemName.text=data.item_name
    binding.mfgName.text=data.mfg
    binding.quantity.text=data.item_stock.toString()



}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    holder.restore()
    bindItems(dataList[position])
    holder.select()



}

@SuppressLint("ResourceAsColor")
inner class ViewHolder(itemView: View):RecyclerView.ViewHolder(itemView) {

   fun restore(){


       for (i in 0 until ob.dataSelected.size){
           for (j in 0 until dataList.size){
                if (ob.dataSelected[i].sku_code==(dataList[j]).sku_code) {


                        if(adapterPosition == j){

                            itemView.isSelected = true
                            itemView.setBackgroundColor(R.color.black)
                            println("****")

                        }
                }

           }
       }

   }


 fun select(){

        itemView.setOnClickListener {



            val position: Int = adapterPosition
            if (ob.dataSelected.contains(dataList[position]) ){
                    itemView.setBackgroundResource(0)
                    itemView.isSelected = false
                 ob.dataSelected.remove(dataList[position])

                for (i in 0 until ob.dataSelected.size){
                    println(ob.dataSelected[i].sku_code)
                }
            }
            else {
                        itemView.isSelected = true
                        itemView.setBackgroundColor(R.color.black)
                        ob.dataSelected.add((dataList.get(position)))
                for (i in 0 until ob.dataSelected.size){
                    println(ob.dataSelected[i].sku_code)
                }

            }
        }


 }



}


override fun getItemCount(): Int {
    return dataList.size
}
override fun getItemId(position: Int): Long = position.toLong()

} . . . . . . 编辑:

class RecyclerViewAdapter(val dataList:ArrayList,val onItemClicked: (Int) -> Unit):RecyclerView.Adapter(){

对象对象{ val dataSelected= ArrayList()

}

private var checkedPosition = -1


fun setData(listModel: List<ModelClass>) {
    dataList.clear()
    dataList.addAll(listModel)
    notifyDataSetChanged()
}




override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
    val binding = ItemViewBinding.inflate(
        LayoutInflater.from(parent.context), parent, false
    )
    return ViewHolder(binding, parent.context)
}


override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    holder.bindItems(dataList[position])
}

override fun getItemCount() = dataList.size

inner class ViewHolder(
    val binding: ItemViewBinding,
    val context: Context
): RecyclerView.ViewHolder(binding.root) {
    @SuppressLint("ResourceAsColor", "ResourceType")
    fun bindItems(data: ModelClass) = with(binding) {
        /*
        * Map Your data Here
        * example: tvTitle.text = model.title
        * */
        binding.itemQuant.text=data.item_quant
        binding.itemName.text=data.item_name
        binding.mfgName.text=data.mfg
        binding.quantity.text=data.item_stock.toString()

        when (checkedPosition) {
            -1 -> {
                itemView.setBackgroundResource(0)
            }
            else -> when (checkedPosition) {
                adapterPosition -> {
                    itemView.setBackgroundColor(R.color.black)

                }
                else -> {
                    itemView.setBackgroundResource(0)
                }
            }
        }
        root.setOnClickListener {
           itemView.setBackgroundResource(R.color.black)
            if (checkedPosition != adapterPosition) {
                notifyItemChanged(checkedPosition)
                checkedPosition = adapterPosition
            }

            // Handle the clicked item

            if (ob.dataSelected.contains(dataList[adapterPosition])){
                ob.dataSelected.remove(dataList[adapterPosition])
                itemView.isSelected=false
                for (i in ob.dataSelected){
                    println(i.sku_code)
                }
                itemView.setBackgroundColor(R.color.black)
            }
            else {
                ob.dataSelected.add(dataList[adapterPosition])
                itemView.isSelected=true
                for (i in ob.dataSelected){
                    println(i.sku_code)
                }
                itemView.setBackgroundResource(0)
            }
            onItemClicked.invoke(adapterPosition)
        }
    }
}

}

这里试试这个,我试过重构你的代码

class RecyclerViewAdapter(
    val onItemClicked: (Int) -> Unit
) : RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder>() {

    private val data = ArrayList<ModelClass>()
    private var checkedPosition = -1 // -1: No Item Selected, 0: First Item Selected

    fun setData(listModel: List<ModelClass>) {
        data.clear()
        data.addAll(listModel)
        notifyDataSetChanged()
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val binding = ItemViewBinding.inflate(
            LayoutInflater.from(parent.context), parent, false
        )
        return ViewHolder(binding, parent.context)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.bindItems(data[position])
    }

    override fun getItemCount() = data.size

    inner class ViewHolder(
        val binding: ItemViewBinding,
        val context: Context
    ): RecyclerView.ViewHolder(binding.root) {
        fun bindItems(model: ModelClass) = with(binding) {
            /*
            * Map Your data Here
            * example: tvTitle.text = model.title
            * */

            when (checkedPosition) {
                -1 -> {
                    clLayout.setBackgroundResource(0)
                }
                else -> when (checkedPosition) {
                    absoluteAdapterPosition -> {
                        clLayout.setBackgroundResource(R.drawable.bg_curved_grey)
                    }
                    else -> {
                        clLayout.setBackgroundResource(0)
                    }
                }
            }
            root.setOnClickListener {
                clLayout.setBackgroundResource(R.drawable.bg_curved_grey)
                if (checkedPosition != absoluteAdapterPosition) {
                    notifyItemChanged(checkedPosition)
                    checkedPosition = absoluteAdapterPosition
                }
                // Handle the clicked item 
                onItemClicked.invoke(absoluteAdapterPosition)
            }
        }
    }
}

这里是你如何在你的Activity或片段

中使用它
private val recyclerViewAdapter: RecyclerViewAdapter by lazy {
    //RecyclerViewAdapter(this::onClickedItem) you can call the function below like this or
    //RecyclerViewAdapter { onClickedItem(it) } or
    RecyclerViewAdapter { position ->
      onClickedItem(position ) 
    }
}

private fun onClickedItem(position: Int) {
    //do something
    Toast.makeText(this, position.toString, Toast.LENGTH_SHORT).show()
}

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(binding.root)

    binding.recyclerview.apply {
        layoutManager = LinearLayoutManager(this)
        adapter = recyclerViewAdapter
    }

    // yourdata = dataList:ArrayList<ModelClass>
    recyclerViewAdapter.setData(yourData)
}

一些解释

它是一个高阶函数,你可以在这里阅读更多Higher order function

val onItemClicked: (Int) -> Unit

用这段代码我们可以删除这个

private lateinit var nListener : onItemClickListener

interface onItemClickListener{
    fun onItemClick(position: Int)

}
fun setOnItemClickListener(listener:onItemClickListener){
    nListener=listener
}

用这段代码

fun setData(listModel: List<ModelClass>) {
    data.clear()
    data.addAll(listModel)
    notifyDataSetChanged()
}

我们使适配器可以灵活处理任何数据集List<ModelClass>