In my application I want use checkbox
in recyclerview
.
I want when users click on item check/unchecked checkbox and when click on Select All or clear, checked/unchecked all of items.
I write below codes, when click on select all checked all of checkboxes but after click on one of checkbox not unchecked!
I should click twice on checkbox after unchecked!
My UI is :
My Adapter codes :
class DataListAdapter @Inject constructor() : RecyclerView.Adapter<DataListAdapter.ViewHolder>() {
private lateinit var binding: ItemWithCheckboxBinding
private lateinit var context: Context
private var moviesList = emptyList<String>()
private var isSelectedAll = false
private var checkBoxState = SparseBooleanArray()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
binding = ItemWithCheckboxBinding.inflate(LayoutInflater.from(parent.context), parent, false)
context = parent.context
return ViewHolder()
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(moviesList[position])
holder.checkBox.isChecked = checkBoxState.get(position, false)
var state: String
if (!isSelectedAll) {
holder.checkBox.isChecked = false
state = LIST_STATE_REMOVE
onItemClickListener?.let { it(moviesList[position], state) }
} else {
holder.checkBox.isChecked = true
state = LIST_STATE_ADD
onItemClickListener?.let { it(moviesList[position], state) }
}
}
override fun getItemCount() = moviesList.size
inner class ViewHolder : RecyclerView.ViewHolder(binding.root) {
val checkBox = binding.itemCheck
@SuppressLint("SetTextI18n")
fun bind(item: String) {
binding.apply {
//Views
itemTitle.text = item
//Click
var state: String
binding.root.setOnClickListener {
if (!checkBoxState.get(adapterPosition, false)) {
checkBox.isChecked = true
checkBoxState.put(adapterPosition, true)
state = LIST_STATE_ADD
} else {
checkBox.isChecked = false
checkBoxState.put(adapterPosition, false)
state = LIST_STATE_REMOVE
}
onItemClickListener?.let { it(item, state) }
}
}
}
}
@SuppressLint("NotifyDataSetChanged")
fun selectAll() {
isSelectedAll = true
notifyDataSetChanged()
}
@SuppressLint("NotifyDataSetChanged")
fun unSelectAll() {
isSelectedAll = false
notifyDataSetChanged()
}
private var onItemClickListener: ((String, String) -> Unit)? = null
fun setOnItemClickListener(listener: (String, String) -> Unit) {
onItemClickListener = listener
}
fun setData(data: List<String>) {
val moviesDiffUtil = NotesDiffUtils(moviesList, data)
val diffUtils = DiffUtil.calculateDiff(moviesDiffUtil)
moviesList = data
diffUtils.dispatchUpdatesTo(this)
}
class NotesDiffUtils(private val oldItem: List<String>, private val newItem: List<String>) : DiffUtil.Callback() {
override fun getOldListSize(): Int {
return oldItem.size
}
override fun getNewListSize(): Int {
return newItem.size
}
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return oldItem[oldItemPosition] === newItem[newItemPosition]
}
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return oldItem[oldItemPosition] === newItem[newItemPosition]
}
}
}
For control select all and clear checkboxes I write codes in Fragment:
selectAllTxt.setOnClickListener { dataListAdapter.selectAll() }
clearTxt.setOnClickListener { dataListAdapter.unSelectAll() }
How can I fix it?
CodePudding user response:
Try to use the !checkBox.isChecked
instead of !checkBoxState.get(adapterPosition, false)
when clicking:
binding.root.setOnClickListener {
if (!checkBox.isChecked) {
checkBox.isChecked = true
checkBoxState.put(adapterPosition, true)
state = LIST_STATE_ADD
} else {
checkBox.isChecked = false
checkBoxState.put(adapterPosition, false)
state = LIST_STATE_REMOVE
}
onItemClickListener?.let { it(item, state) }
}