Forzar ListView a no reutilizar vistas (casilla de verificación)

Hice un Listview personalizado (sin sobreescribir el método getView() ) con cada elemento en un Listview que tiene un siguiente Layout

Contactlayout.xml

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent" android:weightSum="1"> <CheckBox android:id="@+id/checkBox1" android:text="CheckBox" android:layout_width="134dp" android:layout_height="108dp" android:focusable="false"></CheckBox> <LinearLayout android:id="@+id/linearLayout1" android:layout_height="match_parent" android:orientation="vertical" android:layout_width="87dp" android:layout_weight="0.84" android:weightSum="1" > <TextView android:text="TextView" android:layout_height="wrap_content" android:layout_width="match_parent" android:id="@+id/name" android:layout_weight="0.03"></TextView> <TextView android:text="TextView" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/phone"></TextView> <TextView android:text="TextView" android:layout_height="wrap_content" android:layout_weight="0.03" android:layout_width="match_parent" android:id="@+id/contactid" android:visibility="invisible"></TextView> </LinearLayout> </LinearLayout> 

Estoy poblando el Listview usando un SimpleCursorAdapter de una manera siguiente …

 Cursor c = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,null,null, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME); String from[] = new String[]{ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,ContactsContract.CommonDataKinds.Phone.NUMBER,ContactsContract.CommonDataKinds.Phone.CONTACT_ID}; int to[] = new int[]{R.id.name,R.id.phone,R.id.contactid}; SimpleCursorAdapter s = new SimpleCursorAdapter(this,R.layout.contactlayout,c,from,to); lv.setAdapter(s); 

Al hacer clic en un botón estoy leyendo los estados de todas las casillas de verificación. El problema es que, si compruebo un CheckBox varios otros abajo de la línea se comprueba automáticamente. Sé que esto es reutilización de vistas. ¿Cómo lo evito? No estoy incluso sobreescribir getView() método en este caso, así que me pregunto si todavía hay alguna manera de lograr lo que quiero?

Responder

Finalmente implementé lo que @sastraxi sugirió …

 @Override public View getView(int position, View convertView, ViewGroup parent) { View view = super.getView(position, convertView, parent); final CheckBox checkBox = (CheckBox) view.findViewById(R.id.checkBox1); final TextView name = (TextView) view.findViewById(R.id.name); final TextView contactId = (TextView) view.findViewById(R.id.contactid); final int pos = position; checkBox.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub if(checkBox.isChecked()) { checkList.add(String.valueOf(pos)); nameList.add(name.getText().toString()); contactList.add(contactId.getText().toString()); Log.i("Chk added",String.valueOf(pos)); } else { checkList.remove(String.valueOf(pos)); nameList.remove(name.getText().toString()); contactList.remove(contactId.getText().toString()); Log.i("Un Chk removed",String.valueOf(pos)); } } }); if(checkList.contains(String.valueOf(pos))) { checkBox.setChecked(true); } else { checkBox.setChecked(false); } return view; } 

Ah, ya veo cuál es el problema.

Haga una nueva clase que extienda SimpleCursorAdapter , diga CheckboxSimpleCursorAdapter y getView como tal:

 public View getView(int position, View convertView, ViewGroup parent) { View view = super.getView(position, convertView, parent); CheckBox checkBox = (CheckBox) view.findViewById(R.id.CheckBox1); checkBox.setChecked(getIsThisListPositionChecked(position)); return view; } 

Como no está utilizando un diseño cuya View nivel superior implementa Checkable , tiene que hacerlo todo usted mismo. Eso incluye el estado de borrado (en este caso), ya que la implementación por defecto reutilizó una View que fue marcada – como intuiste correctamente.

Editar: utilice este nuevo código e implemente un protected boolean getIsThisListPositionChecked(int position) que devuelve si el elemento está actualmente marcado (o algo así). Espero que esté siendo bastante claro – usted necesita calcular hacia fuera si el artículo se debe comprobar según su modelo, y después fijar eso cuando usted crea la View .

Otra forma de forzar la no reutilización de las vistas, agregue lo siguiente en su adaptador de cursor:

  @Override public int getItemViewType(int position) { return position; } @Override public int getViewTypeCount() { return 500; } 

Pero sí, debe reutilizar las vistas siempre que sea posible. En mi caso particular, estoy añadiendo imágenes a mis puntos de vista y sin forzar a no reutilizar la vista, se volverían a representar en las vistas reutilizadas.

Siempre es mejor reutilizar las vistas. Lo que está tratando de lograr se puede hacer con unos pocos ajustes en su código. Debe registrar el control de sus casillas de verificación usando otra lista de variables (un booleano para cada elemento de lista).

Anule estos dos métodos en la clase Adaptador

  @Override public int getViewTypeCount() { return getCount(); } @Override public int getItemViewType(int position) { return position; } 
  • ListView de Android Actualizar animación
  • Reposicionar la barra de desplazamiento de ListView con relleno
  • Android ListView automáticamente Carga más datos cuando se desplaza a la parte superior
  • Cómo obtener la altura del teclado cuando la actividad creada en android
  • Android.view.InflateException: Línea de archivo XML binario # 9: Error al inflar la clase <unknown>
  • Altura dinámica para la fila ListView en android
  • Android listview obtiene el elemento seleccionado
  • Listview con un adaptador personalizado que contiene CheckBoxes
  • Flujo de trabajo de facturación en la aplicación en un ListView
  • Línea negra bajo algunos elementos ListView
  • Estado de comprobación de ListView Viewholder
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.