Bench
Bench

Reputation: 53

double check Android studio in list view

I have a problem developing Android application

The project is being developed in Android Studio, with the programming language Kotlin

I was trying to implement a custom adapter to a list, however when I run the program a selection error is generated, this error is as follows:

When one of the boxes is selected, with an id n, if n is odd, all the odd boxes are marked, and it happens the same when n is even, all the boxes with the same id are marked.

I attach the code of the template, the view and the class that interact in the part of the program when the error is generated.

Template:

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent">

<CheckBox
    android:id="@+id/cbCheck"
    android:layout_width="wrap_content"
    android:layout_height="67dp"
    android:layout_weight="1"
    android:text="CheckBox"
    android:textAlignment="textStart"
    android:textAppearance="@style/TextAppearance.AppCompat.Display1"
    android:textSize="24sp" />
</LinearLayout>

Main Layout:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="5dp"
    android:orientation="vertical"
    tools:context=".ServiciosServicioActivity">

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="8dp"
        app:layout_constraintTop_toBottomOf="@+id/tViewServicio"
        tools:layout_editor_absoluteX="8dp">

        <LinearLayout
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:orientation="vertical">

             <ListView
                android:id="@+id/listViewRequisitos"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                tools:layout_editor_absoluteX="22dp"
                tools:layout_editor_absoluteY="300dp" />

         </LinearLayout>
     </ScrollView>
</LinearLayout>

Class code:

class ServiciosServicioActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_servicios_servicio)

    val nombre = intent.getStringExtra("Nombre")
    val encargado = intent.getStringExtra("Encargado")
    val requisitos = intent.getStringArrayListExtra("Requisitos")

    val tViewNombre = findViewById<TextView>(R.id.tServicio)
    val tViewEncargado = findViewById<TextView>(R.id.tEncargadoServicio)
    val lViewRequisitos = findViewById<ListView>(R.id.listViewRequisitos)

    tViewNombre?.text = nombre
    tViewEncargado?.text = encargado
    val adaptador = AdaptadorCheck(this, requisitos)
    lViewRequisitos.adapter = adaptador
}
}

Adapter Code:

class AdaptadorCheck(var context: Context, items: ArrayList<String>):BaseAdapter() {
    private var items:ArrayList<String> = ArrayList()
    init{ this.items = items }

    override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
        var holder: AdaptadorCheck.ViewHolder? = null
        var vista:View? = convertView

        if(vista == null ){
            vista = LayoutInflater.from(context).inflate   (R.layout.template_check, null)
            holder = AdaptadorCheck.ViewHolder(vista)
            vista.tag = holder
        }else{
            holder = vista.tag as? AdaptadorCheck.ViewHolder
        }

        val item = getItem(position) as String
        holder?.nombre?.text = item

        return vista!!
    }

    override fun getItem(position: Int): Any {
        return items?.get(position)!!
    }

    override fun getItemId(position: Int): Long {
        return position.toLong()
    }

    override fun getCount(): Int {
        return items?.count()!!
    }

    private class  ViewHolder(vista: View){
        var nombre: CheckBox? = null
        init{
            nombre = vista.findViewById(R.id.cbCheck)
        }
    }
}

Upvotes: 3

Views: 215

Answers (1)

Ranjan
Ranjan

Reputation: 1146

So I tried exact same code and I found out the problem. To understand it, you'll have to first understand how listView works. From the documentation -

ListView attempts to reuse view objects in order to improve performance and avoid a lag in response to user scrolls. https://developer.android.com/reference/android/widget/ListView

Problem with your code is that your listview's height is wrap_content and because of that only 1 view is visible. So when you scroll down, listView reuse view from the top. So when you come to 3rd view, listView reuse view at position 1 and since your checkbox is reused, it shows as if 3rd view's checkbox was already checked.

Few things I would suggest.

  • When you are going to take input from user in a list, you'll have to store it somewhere in an local array, so that you can retrieve those values again. Otherwise they'll just get lost when user scrolls.
  • You can make an array which stores boolean values and depending on boolean value you'll update your checkbox. Also update this array when user changes value of any checkbox. It should work vice versa. Showing latest state of checkbox from the array and updating the array when checkbox is selected/unselected. This you'll do in getView method of adapter.
  • Also I have never seen anyone use wrap_content over a listView. Probably you are trying to something else and not finding the right View to do it.
  • You can try changing the width of listView and see that there is nothing wrong with your code.
  • Go for recyclerView instead. It is an improvement to listView.

Upvotes: 2

Related Questions