android - RecyclerView取消选择之前选择的复选框

标签 android kotlin android-recyclerview

我将 RecyclerView ViewHolder 作为复选框,单击该复选框后,我需要取消选择已选中的其他复选框,但它没有发生,更改不会反射(reflect)在 View 中。

回收器项目单击在单击时在 onBindViewHolder 中初始化,插槽数据已更新并调用了 notificationItemChanged,但占位符未更新,我是否错过了更新 View 持有者的任何内容。

override fun onBindViewHolder(
    holder: BookingSlotListItemViewHolder,
    position: Int,
    payloads: MutableList<Any?>
 )

class BookingSlotListAdapter(
    private val hourSlotHolder: RecyclerView,
    private val bookingBtn: TextView
    ) : RecyclerView.Adapter<BookingSlotListItemViewHolder>() {
    private val bookingSlots = ArrayList<BookingSlotAvailability>()
    private var lastSelected: Int? = null
    private val bookingHourItemAdapter = BookingHourItemAdapter(bookingBtn)
    private val NOT_SELECTED_FOR_BOOKING = 0
    private val AVAILABLE_FOR_BOOKING = false

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BookingSlotListItemViewHolder {
        val layoutInflater: LayoutInflater = LayoutInflater.from(parent.context)
        val view = layoutInflater.inflate(R.layout.booking_time_slot, parent, false)
        return BookingSlotListItemViewHolder(view)
    }

    override fun getItemCount(): Int {
        if (bookingSlots.isNullOrEmpty()) {
        return 0
        }
        return bookingSlots.size
    }

    fun setBookingSlots(bookingSlots: TreeMap<String, Boolean>) {
        bookingSlots.map {
            this.bookingSlots.add(BookingSlotAvailability(it.key, it.value, NOT_SELECTED_FOR_BOOKING))
        }
    }

    override fun onBindViewHolder(holder: BookingSlotListItemViewHolder, position: Int) {
        holder.timeSlot.text = bookingSlots[position].time
        if (!bookingSlots[position].isAvailable) {
        holder.timeSlot.isEnabled = false
        }
        if (bookingSlots[position].selectionStatus == 0 && holder.timeSlot.isChecked) {
        holder.timeSlot.toggle()
        } else if (bookingSlots[position].selectionStatus == 1 && !holder.timeSlot.isChecked) {
        holder.timeSlot.toggle()
        }

        holder.timeSlot.setOnClickListener { view: View? ->
        Log.v("CLICKED", "BookingSlotListAdapter: $lastSelected : $position")
        val selectedSlot = view as CheckBox

        if (lastSelected != null) {
            bookingSlots[lastSelected!!].isAvailable = AVAILABLE_FOR_BOOKING
            bookingSlots[lastSelected!!].selectionStatus = NOT_SELECTED_FOR_BOOKING
            notifyItemChanged(
            lastSelected,
            bookingSlots[lastSelected!!]
            )
        }
        bookingSlots[position].isAvailable = NOT_AVAILABLE
        bookingSlots[position].selectionStatus = SELECTED_FOR_BOOKING
        notifyItemChanged(
            position,
            bookingSlots[position]
        )
        lastSelected = position
        }
    }

    override fun onBindViewHolder(
        holder: BookingSlotListItemViewHolder,
        position: Int,
        payloads: MutableList<Any?>
    ) {
        super.onBindViewHolder(holder, position, payloads)
        Log.v("OVERLOADEDVH", "$payloads $position")
    }
}

最佳答案

您需要在 onBindViewholder 方法中对其进行选中/取消选中,因为它会重用 View 并在我们滚动 recyclerView 时再次创建 View ,因此它不知道 checkBox 的最后状态:

    // Add these lines below at then end of onBindViewHolder
    val selectedSlot = holder.timeSlot as CheckBox

    if(lastSelected == position){
        selectedSlot.isChecked = true;
    }else{
        selectedSlot.isChecked = false;
    } 

要更新旧复选框以取消选择,请调用 notifyDataSetChanged(),这样将为所有可见单元格再次调用 onBindHolder(),并相应更新。

在设置 lastSelected pos 后调用 notifyDataSetChanged() :

    holder.timeSlot.setOnClickListener { view: View? ->
    Log.v("CLICKED", "BookingSlotListAdapter: $lastSelected : $position")
    val selectedSlot = view as CheckBox

    if (lastSelected != null) {
        bookingSlots[lastSelected!!].isAvailable = AVAILABLE_FOR_BOOKING
        bookingSlots[lastSelected!!].selectionStatus = NOT_SELECTED_FOR_BOOKING

        //COMMENT  notifyDataSetChanged WILL HANDLE ALL
        //notifyItemChanged(
        //lastSelected,
        //bookingSlots[lastSelected!!]
        //)
    }
    bookingSlots[position].isAvailable = NOT_AVAILABLE
    bookingSlots[position].selectionStatus = SELECTED_FOR_BOOKING

    //COMMENT  notifyDataSetChanged WILL HANDLE ALL
    //notifyItemChanged(
    //    position,
    //    bookingSlots[position]
    //)
    lastSelected = position

     //------CALL notifyDataSetChanged() for all visible cells------
     notifyDataSetChanged() ;


    }

关于android - RecyclerView取消选择之前选择的复选框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57098873/

相关文章:

javafx - 如何在JavaFX的MenuButton中创建子菜单?

Android RecyclerView 找出 ItemDecoration 上的第一个和最后一个 View

android - 使用 Phonegap 离线显示和导航大型自定义 map

java - 您能指导我代码中有什么问题吗?

android - 在 TextInputLayout 中使用 endIconMode 默认情况下启用结束图标(可见图标)

android - 为什么我的 RX 链中得到的是 KFunction1 而不是 List<E>?

android-recyclerview - Android 滚动到 Recyclerview 中的位置不起作用

android - 如何在 recyclerview 项目之间设置相等的边距

android - 带有输入流的 httpclient 多部分发布

Android - 如何以编程方式启动设备 "file system"?