I'm having problems with the following case, I have my list of questions with their respective check boxes, what I can't understand is why when I click check on "Yes" other boxes are checked, does anyone know why this anomaly happens.
This is the "yes" frame problem in question 1 and it is marked in question 8, 14 and so on randomly.
This is my structure.xml that contains the checkboxes
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:animateLayoutChanges="true"
app:cardCornerRadius="2dp"
app:cardElevation="4dp"
app:cardUseCompatPadding="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="true"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@ id/icosemaforo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="@drawable/ic_android" />
</RelativeLayout>
<LinearLayout
android:id="@ id/contenedor_categoria1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:orientation="vertical"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<TextView
android:id="@ id/txtnumeropregunta"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:layout_alignParentTop="true"
android:text="N°"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:id="@ id/txtpreguntas"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="20dp"
android:layout_toStartOf="@ id/contenedorcheck"
android:textSize="14sp"
android:layout_toEndOf="@ id/txtnumeropregunta"
android:textStyle="bold"
android:text="Preguntas" />
<LinearLayout
android:id="@ id/contenedorcheck"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:paddingEnd="20dp"
>
<CheckBox
android:id="@ id/chbksi"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:text="@string/check_si" />
<CheckBox
android:id="@ id/chbkIVSS"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:visibility="gone"
android:text="@string/check_IVSS" />
<CheckBox
android:id="@ id/chbkFSERV"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:visibility="gone"
android:text="@string/check_freserv" />
<CheckBox
android:id="@ id/chbkno"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:text="@string/check_no" />
<CheckBox
android:id="@ id/chbkfmano"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
android:layout_marginEnd="10dp"
android:text="@string/check_fredmano" />
<CheckBox
android:id="@ id/chbkDSS"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
android:layout_marginEnd="10dp"
android:text="@string/check_DSS" />
<CheckBox
android:id="@ id/chbkna"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
android:layout_marginEnd="10dp"
android:text="@string/check_na" />
</LinearLayout>
</RelativeLayout>
</LinearLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
And this is my adapter.tk where I hide and show some custom boxes
class preusoadapter(private val listpreguntaspreuso: ArrayList<epreguntas>) : RecyclerView.Adapter<PreUsoViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PreUsoViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
return PreUsoViewHolder(layoutInflater.inflate(R.layout.activity_estructura_listapreuso, parent, false))
}
override fun onBindViewHolder(holder: PreUsoViewHolder, position: Int) {
val item = listpreguntaspreuso[position]
holder.render(item)
holder.itemView.chbksi.isChecked = item.checkvalor != false
if (position == 2)
{
holder.itemView.chbkno.visibility = View.GONE
holder.itemView.chbksi.visibility = View.GONE
holder.itemView.chbkIVSS.visibility = View.VISIBLE
holder.itemView.chbkDSS.visibility = View.VISIBLE
}else if (position == 6){
holder.itemView.chbkFSERV.visibility = View.VISIBLE
holder.itemView.chbkfmano.visibility = View.VISIBLE
holder.itemView.chbkno.visibility = View.GONE
holder.itemView.chbksi.visibility = View.GONE
}else if (position == 14){
holder.itemView.chbkna.visibility = View.VISIBLE
}else if (position == 18){
holder.itemView.chbkna.visibility = View.VISIBLE
}else if (position == 22){
holder.itemView.chbkna.visibility = View.VISIBLE
}else if (position == 25){
holder.itemView.chbkna.visibility = View.VISIBLE
}
else{
holder.itemView.chbkno.visibility = View.VISIBLE
holder.itemView.chbksi.visibility = View.VISIBLE
holder.itemView.chbkna.visibility = View.GONE
holder.itemView.chbkIVSS.visibility = View.GONE
holder.itemView.chbkDSS.visibility = View.GONE
holder.itemView.chbkFSERV.visibility = View.GONE
holder.itemView.chbkfmano.visibility = View.GONE
}
}
override fun getItemCount(): Int = listpreguntaspreuso.size
this is my class equestions(epreguntas)
class epreguntas(
var id_pregunta: String,
var num_pregunta: String,
var pregunta : String,
var icono_estado: String,
var checkvalor: Boolean
) {
}
any ideas on how to handle these events and prevent it from randomly checking other boxes.
CodePudding user response:
If you want some checked state for your list items, you need to do three things:
- store the checked state for the items, e.g. in the data itself, or (better) some data structure in the adapter
- add a listener on your checkboxes that stores the checked/unchecked state for the current item
- read that checked state in
onBindViewHolder
(where you're setting up aViewHolder
to display the current item) and check/uncheck the box as appropriate
I looked at your original question (before the edit) and I see you've added a checked boolean (checkvalor
) to your Epreguntas
data object, to store whether that item is checked or not. Personally I wouldn't do that - I feel like the checked state is a property of the list and not the data itself. So I'd store the checked state in a separate Set
of all the checked position Int
s, or a SparseBooleanArray
where each index holds the checked state for position
. But you can store it in the data object if you like!
So now you have somewhere to store the checked state, you need to set it when the checkbox is clicked, and read it when displaying an item.
You can set it with a click listener - I prefer this to an OnCheckedChangedListener
because it only fires when the user taps it, and not when you set its checked state:
// I prefer setting the click listener in the ViewHolder class, but just to make things simple
override fun onBindViewHolder(holder: PreUsoViewHolder, position: Int) {
val item = listpreguntaspreuso[position]
holder.yourCheckBox.setOnClickListener {
// toggle the checked state
item.checkvalor = !item.checkvalor
// update the display
notifyItemChanged(position)
}
Now your state changes in your item when the checkbox is clicked, so this line should work now:
holder.itemView.chbksi.isChecked = item.checkvalor != false
which you can just write as holder.itemView.chbksi.isChecked = item.checkvalor
btw
A problem with storing your checked state in the data like this, is you have to persist it. If your Activity gets destroyed (e.g. during a rotation) or your whole app is recreated after being in the background, do you have those checkvalor
values stored somewhere? Or will the data be recreated, with all the checkvalor
values set to false?
If you store them in something like a SparseBooleanArray
instead
// create a checked state lookup
private val checked = SparseBooleanArray(listpreguntaspreuso.size)
// read the checked state for an item
val isChecked = checked[position]
// toggle the checked state
checked[position] != checked[position]
then you can easily store that state when the parent Activity or Fragment hits onStop
or onSaveInstanceState
, and restore it when the parent is recreated. I've outlined that here if you want to look into it