chekbox always checking last item in recyclerview - android

i want to get item from checked checkbox in my recyclerview item, this my adapter
class SelectedListDateAdapter(var listDate: List<DateDay>, private val onItemCheckListener: OnItemCheckListener) :
RecyclerView.Adapter<SelectedListDateAdapter.SelectedListDateViewHolder>() {
lateinit var binding: ItemCheckBoxDateBinding
inner class SelectedListDateViewHolder(item: ItemCheckBoxDateBinding) : RecyclerView.ViewHolder(item.root) {
val checkBoxList = item.checkBox
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SelectedListDateViewHolder {
binding = ItemCheckBoxDateBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
return SelectedListDateViewHolder(binding)
}
override fun onBindViewHolder(holder: SelectedListDateViewHolder, position: Int) {
holder.checkBoxList.setOnCheckedChangeListener(null)
holder.checkBoxList.isChecked = listDate[position].isSelected
holder.itemView.apply {
val currentItem = listDate[position]
binding.tvDateList.text = listDate[position].date
setOnClickListener {
binding.checkBox.isChecked = !binding.checkBox.isChecked
if (binding.checkBox.isChecked) {
binding.checkBox.setOnCheckedChangeListener { buttonView, isChecked ->
currentItem.isSelected = isChecked
}
onItemCheckListener.onItemCheck(currentItem)
} else {
binding.checkBox.setOnCheckedChangeListener { buttonView, isChecked ->
currentItem.isSelected = isChecked
}
onItemCheckListener.onItemUncheck(currentItem)
}
}
}
}
override fun getItemCount(): Int {
return listDate.size
}
}
im referring to this question get list of checked item to make that adapter
yes, it get the item and remove them but everytime i click an item in recyclerview it always check and uncheck the last item
i have checking this question CheckBox in RecyclerView keeps on checking different items but my result still the same, any help is appreciated

Maybe viewHolder reuse the previous item.Try to update listData, not currentItem.
And move the nested Listener
override fun onBindViewHolder(holder: SelectedListDateViewHolder, position: Int) {
holder.itemView.tvDateList.text = listDate[position].date
holder.checkBoxList.isChecked = listDate[position].isChecked
holder.checkBoxList.setOnClickListener {
listDate[position].isSelected = holder.checkBoxList.isChecked
}
holder.itemView.setOnClickListener {
holder.checkBoxList.isChecked = !holder.checkBoxList.isChecked
listDate[position].isSelected = holder.checkBoxList.isChecked
val currentItem = listDate[position]
if (holder.checkBoxList.isChecked) {
onItemCheckListener.onItemCheck(currentItem)
} else {
onItemCheckListener.onItemUncheck(currentItem)
}
}
}

Related

How to select all checkboxes in recyclerview on click?

I display several items in the recyclerview, each item has its own checkbox, I want to select the necessary ones and delete them. I did this part and it works well, but I can’t do select all items, please tell me what’s wrong.
Here is my code:
initRecyclerView
private fun initRecyclerView() {
binding.recyclerView.setHasFixedSize(true)
val adapter = AdapterList(requireActivity(), arrayList)
binding.recyclerView.layoutManager = LinearLayoutManager(requireActivity().applicationContext, LinearLayoutManager.VERTICAL, false)
binding.recyclerView.adapter = adapter
}
My function for checkbox in fragment:
binding.allCheckBox.setOnClickListener {
if (isAllSelect) {
AdapterList().unselectAll()
isAllSelect = false
} else {
AdapterList().selectAll()
isAllSelect = true
}
}
My adapter
class AdapterList(private val activity: Activity? = null, private var recyclerList: ArrayList<Info>? = null) :
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
return (holder as ViewHolder).bind(recyclerList!![position])
}
override fun getItemCount(): Int {
return recyclerList!!.size
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return ViewHolder(LayoutInflater.from(activity).inflate(R.layout.item_layout, parent, false))
}
private var isSelectedAll = false
#SuppressLint("NotifyDataSetChanged")
fun selectAll() {
isSelectedAll = true
notifyDataSetChanged()
}
#SuppressLint("NotifyDataSetChanged")
fun unselectAll() {
isSelectedAll = false
notifyDataSetChanged()
}
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
private var binding: ItemLayoutBinding = ItemLayoutBinding.bind(view)
#SuppressLint("NotifyDataSetChanged")
fun bind(list: Info) {
binding.apply {
cardIcon.setImageDrawable(list.icon)
cardName.text = list.name
cardCheckBox.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean ->
recyclerList!![position].checked = isChecked
notifyDataSetChanged()
}
cardCheckBox.isChecked = isSelectedAll
}
}
}
}
Now it crashes on clicking on the checkbox in cardview because of the line
cardCheckBox.isChecked = isSelectedAll
in Adapter
Tried to do as described here but does not work Select all checkboxes in RecyclerView
If I do so
binding.allCheckBox.setOnClickListener {
if (isAllSelect) {
for (list in arrayList) {
list.checked = false
}
isAllSelect = false
} else {
for (list in arrayList) {
list.checked = true
}
isAllSelect = true
}
}
By clicking on the delete button, I see that the data is correct, but the checkbox in the recyclerview is not updated (notifyDataSetChanged() does not work?), and I'm not sure if this approach is correct

Expand/Collapse groups RecyclerView header

I'm trying to create a RecyclerView adapter with two types of items. First one is Header, second one is child item. And when user tap on Header item it will expand child items. Next tap will collapse current section of items. But when I tap on Header in my RecyclerView it shows expanded items after second header. I don't know how to fix it
class SectionedAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private var items = mutableListOf<ListItem>()
fun setItems(items: MutableList<ListItem>) {
this.items = items
notifyDataSetChanged()
}
class HeaderItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(item: HeaderItem) = with(itemView) {
textViewHeader.text = item.title
}
}
class TextItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(item: TextItem) = with(itemView) {
textViewTitle.text = item.title
textViewContent.text = item.content
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return when(viewType) {
TYPE_HEADER -> {
val headerView = LayoutInflater.from(parent.context).inflate(R.layout.item_header, parent, false)
return HeaderItemViewHolder(headerView)
}
TYPE_TEXT -> {
val textView = LayoutInflater.from(parent.context).inflate(R.layout.item_text, parent, false)
return TextItemViewHolder(textView)
}
else -> throw IllegalArgumentException()
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val item = items[position]
when(holder) {
is HeaderItemViewHolder -> {
holder.bind(item as HeaderItem)
holder.itemView.setOnClickListener {
if(item.expanded) {
items.addAll(item.items)
notifyItemRangeInserted(position, item.items.size)
}
else {
items.removeAll(item.items)
notifyItemRangeRemoved(position, item.items.size)
}
item.expanded = !item.expanded
}
}
is TextItemViewHolder -> {
holder.bind(item as TextItem)
}
else -> throw IllegalArgumentException()
}
}
override fun getItemCount(): Int {
return items.count()
}
override fun getItemViewType(position: Int): Int {
val item = items[position]
return when(item) {
is HeaderItem -> TYPE_HEADER
is TextItem -> TYPE_TEXT
else -> throw IllegalArgumentException()
}
}
companion object {
const val TYPE_HEADER = 0
const val TYPE_TEXT = 1
}
}
I think what you are trying to achieve would be easier to do with nested Recyclerviews.
In your item_header.xml add a recyclerview, in onBindViewHolder, initialize this subRecyclerView for every sublist, initialize its adapter etc, populate this sub recyclerview with your required items, and let your onclick listener expand / collapse this sub recyclerView by setting its visibility to View.GONE (parent views layout height needs to be set to wrap_content for this to work)

Check box in recyclerview is automatically unchecked when scrolling in android

I have created a view using recyclerview adapter for listing students. My problem is that when i am scrolling the view all the checked checkboxes are automatically unchecked. Which means the states are changing.How to overcome the issue
Here i shared my code. Please check and suggest a solution. Thanks in advance.
class IndividualStudentSelectAdapter(private val context: Context,
private var students: List<IndividualStudentBean>,
private val checkBox1: CheckBox,
private val individualStudentSelectionListener: IndividualStudentSelectionListener
)
: RecyclerView.Adapter<IndividualStudentSelectAdapter.ViewHolder>(){
companion object {
val TAG: String = IndividualStudentSelectAdapter::class.java.simpleName
}
override fun onCreateViewHolder(p0: ViewGroup, p1: Int): IndividualStudentSelectAdapter.ViewHolder {
return ViewHolder(LayoutInflater.from(context).inflate(R.layout.individual_student, p0, false))
}
override fun getItemCount(): Int {
return students.size
}
override fun onBindViewHolder(p0: ViewHolder, p1: Int) {
val user = students.get(p1)
p0.bindView(p1)
p0.binding.individualStudentBean = students[p1]
if (user.getSelected()==true) {
p0.checkbox2.isChecked = true
} else {
p0.checkbox2.isChecked = false
}
p0.checkbox2.setOnCheckedChangeListener { buttonView, isChecked ->
if(isChecked)
{
// val individualStudentBean = IndividualStudentBean(user.empid,"","")
Log.d("admnos",user.id)
individualStudentSelectionListener.addDatas(user.id)
user.setSelected(true)
}else{
individualStudentSelectionListener.removeDatas(user.id)
user.setSelected(false)
}
}
checkBox1.setOnCheckedChangeListener {
buttonView, isChecked ->
if (isChecked){
for (item in students)
{
p0.checkbox2.isChecked = true
item.setSelected(true)
notifyDataSetChanged()
}
}else{
for (item in students) {
p0.checkbox2.isChecked = false
item.setSelected(false)
notifyDataSetChanged()
}
}
}
}
fun updateDataset(students: List<IndividualStudentBean>) {
this.students = students
notifyDataSetChanged()
}
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var binding: IndividualStudentBinding = DataBindingUtil.bind(itemView)!!
val checkbox2 = itemView.findViewById(R.id.cb_student) as CheckBox
fun bindView(position: Int) {
// this.setIsRecyclable(false)
binding.individualStudentBean = students[position]
itemView.setOnClickListener {
//students[position].selected = itemView.cb_student.isChecked
if (context is IndividualStudentSelectActivity) {
//context.onStudentSelected()
}
if (context is IndividualStudentSelectActivity) {
//context.onStudentSelected()
}
}
}
}
}
add a Property called isChecked (the name depends on your choice) to your Student data class, then add this code in bindView method
checkbox2.isChecked = students[adapterPosition].isChecked
checkbox2.setOnCheckedChangeListener { _, isChecked ->
students[adapterPosition].isChecked = isChecked
}

Select only one check box ; RecyclerView; Kotlin

It's my code and I want to choose only one checkbox, and if another checkbox is selected I want that this convert in uncheked
class AuthorizationFormAdapter(lista: List<Procedures>?) : RecyclerView.Adapter<AuthorizationFormAdapter.ViewHolder>() {
val lista: List<Procedures>? = lista
lateinit var array: BooleanArray
class ViewHolder(val view: View) : RecyclerView.ViewHolder(view) {
val text: TextView? = null
val checkBox: CheckBox? = null
}
override fun onCreateViewHolder(parent: ViewGroup, p1: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.card_authform, parent, false)
return ViewHolder(view)
}
override fun getItemCount(): Int {
return lista!!.size
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.view.auth_name.text = lista!![position].name_procedure
holder.view.cb_auth.setOnClickListener {
if (holder.view.cb_auth.isChecked) {
holder.view.cb_auth.isSelected = true
} else if (!holder.view.cb_auth.isChecked) {
holder.view.cb_auth.isChecked = false
}
}
}
}
And Xml is only one checkBox and textView in my card
I will be very grateful with your help
You have to create a field in your Procedures to store the checked/unchecked state
var isChecked: Boolean = false
Then inside your adapter store lastCheckedPosition and unchecked when user select other.
class AuthorizationFormAdapter(lista: List<Procedures>?) : RecyclerView.Adapter<AuthorizationFormAdapter.ViewHolder>() {
var lastCheckedPosition: Int = 0
....
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val procedure = lista!![position]
holder.view.auth_name.text = procedure.name_procedure
holder.view.cb_auth.isChecked = procedure.is_checked
holder.view.cb_auth.setOnCheckedChangeListener { buttonView, isChecked ->
if(isChecked) {
lista!![lastCheckedPosition].is_checked = false
lastCheckedPosition = position
}
lista!![position].is_checked = isChecked
notifyDataSetChanged() // This is important to reload the list
}
}
}

How to show single item selected in recyclerview using kotlin

How can we mark single item is selected in Recyclerview using kotlin. When I select an item and after that click on other item then previously selected item should be dis-selected.Here is my adapter class in kotlin:..
class ListAdapter(var context: Context, var list: ArrayList<ListModel>) : RecyclerView.Adapter<ListAdapter.MyViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): MyViewHolder {
val v = LayoutInflater.from(parent?.context).inflate(R.layout.list_item, parent, false)
return MyViewHolder(v)
}
override fun getItemCount(): Int {
return list.size
}
override fun onBindViewHolder(holder: MyViewHolder?, position: Int) {
holder?.bindItems(list[position])
}
class MyViewHolder(view: View) : RecyclerView.ViewHolder(view){
fun bindItems(items: ListModel) {
itemView.txt_que.text = items.que
itemView.txt_ans.text = items.ans
itemView.txt_sr_no.text = items.srNo
}
}`
Here dataItem is Model Class and please take one extra Boolean variable isSelected in model class (default value is false) and true when select item then true this variable on selected position,
below are example :
class AllModuleListAdapter(
var context: Context?,
private var moduleList: ArrayList<DataItem?>?,
private var mCallback: DeviceClickListener
) :
RecyclerView.Adapter<AllModuleListAdapter.MyViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val context = parent.context
val itemView = LayoutInflater.from(context).inflate(R.layout.item_modules, parent, false)
return MyViewHolder(itemView)
}
override fun getItemCount(): Int {
return moduleList?.size ?: 0
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.bind(moduleList?.get(position))
if (moduleList?.get(position) is DataItem) {
val dataItem = moduleList?.get(position) as DataItem
if (dataItem.isSelected) {
context?.let { ContextCompat.getColor(it, R.color.colorOrange) }
?.let { holder.itemView.setBackgroundColor(it) }
} else {
context?.let { ContextCompat.getColor(it, R.color.white) }
?.let { holder.itemView.setBackgroundColor(it) }
}
}
}
inner class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
init {
itemView.constraint_main.setOnClickListener {
val list = moduleList as List<DataItem>
for (item in list.indices) {
list[item].isSelected = false
}
list[adapterPosition].isSelected = true
mCallback.onDeviceClick(adapterPosition)
notifyDataSetChanged()
context?.let { it1 -> ContextCompat.getColor(it1, R.color.colorOrange) }?.let { it2 ->
itemView.constraint_main?.setBackgroundColor(it2)
}
}
}
fun bind(module: DataItem?) {
itemView.txtModuleName?.text = module?.id.toString()
itemView.txtSignal?.text = module?.room
}
}
}
if (mPosition == position)
{
//set selected here
} else
{
//set unselected here
}
holder.parentView.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View view)
{
mPosition = position;
notifyDataSetChanged();
}
});
Write above code in onBindViewholder and declare mPosition as global int variable in adapter class
Try with this:- take one variable in your ListModel class as
var selected:boolean = false
then while setting the listModel items set this value as false as
for(int i=0;i<listModel.size;i++){
listModel.get(i).selected = false
}//this is for setting all values false
when you select any item from list call this method and then set selected = true for selected position and simply refresh the adapter list.
in your adapter check for this selected value and accordingly set the check box value inside your bindItems method
itemView.checkBox.selected = items.selected//this will set your checkbox selected value

Categories

Resources