Estado de comprobación de ListView Viewholder
Tengo algunos problemas con mi adaptador personalizado ListView (y su nuevo viewHolder implementado). Tengo un ListView con una casilla de verificación para cada elemento (nada nuevo aquí). El problema es que si hay más de 9 elementos en mi lista, cuando compruebo la primera casilla, la décima será automáticamente marcada (igual para la segunda con la undécima), como si hubiera un oyente para ambos ítem Cree que es el caso de alguna manera).
He leído sobre la cuestión de la posición con listView, ver el reciclaje y la forma ViewHolder para resolverlo aquí: ¿Cómo puedo hacer que mi ArrayAdapter siga el patrón ViewHolder?
- Cómo mostrar las casillas de verificación pre verificadas en android
- Android: ¿Cómo cambiar el tamaño de CheckBox?
- Desarrollo de Android: Checkbox setChecked no funciona
- ¿Cómo acceder a la marca de verificación en el sistema operativo Android?
- El clic de Listitem no funciona con las casillas de verificación Android
Pero probablemente hice algo mal porque no está funcionando …
public class PresenceListAdapter extends SimpleAdapter { private LayoutInflater inflater; private List<Integer> ids; private List<String> statuts; public PresenceListAdapter (Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to, List<Integer> ids, List<String> statuts) { super (context, data, resource, from, to); inflater = LayoutInflater.from (context); this.ids = ids; this.statuts= statuts; } @Override public Object getItem (int position) { return super.getItem (position); } @Override public View getView (int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { convertView = inflater.inflate (R.layout.list_text_checkbox, null); holder = new ViewHolder(); holder.btn = (Button) convertView.findViewById(R.id.btnRetard); holder.check = (CheckBox) convertView.findViewById(R.id.checkPresent); if (statuts.get(position).equals("P")) { Drawable img = inflater.getContext().getResources().getDrawable(android.R.drawable.presence_online); holder.btn.setCompoundDrawablesWithIntrinsicBounds( img, null, null, null ); holder.btn.setEnabled(true); holder.check.setChecked(true); } else if(statuts.get(position).equals("R")) { Drawable img = inflater.getContext().getResources().getDrawable(android.R.drawable.presence_away); holder.btn.setCompoundDrawablesWithIntrinsicBounds( img, null, null, null ); holder.btn.setEnabled(true); holder.check.setChecked(true); } else { Drawable img = inflater.getContext().getResources().getDrawable(android.R.drawable.presence_invisible); holder.btn.setCompoundDrawablesWithIntrinsicBounds( img, null, null, null ); holder.check.setChecked(false); } convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } int id = ids.get(position); if(id != 0) { holder.check.setTag(id); holder.btn.setTag(id); } return super.getView (position, convertView, parent); } static class ViewHolder { Button btn; CheckBox check; }
Y mi oyente: public void changerPresent (View v) {
CheckBox checkPresent = (CheckBox) v; int idPersonne = (Integer) checkPresent.getTag(); View parent = (View)v.getParent(); Button btn = (Button) parent.findViewById(R.id.btnRetard); if(checkPresent.isChecked()) { gestion.updatePresence(idPersonne, idSeance, "P"); btn.setEnabled(true); setBtnRetardPresent(btn); } else { gestion.updatePresence(idPersonne, idSeance, "A"); btn.setEnabled(false); setBtnRetardAbsent(btn); } }
Agradecería cualquier ayuda en este punto, estoy trabajando en esto por horas ahora.
Muchas gracias.
- La imagen personalizada de CheckBox se corta
- Android: ¿Cómo puedo comprobar un elemento en particular en CheckView ListView?
- Hacer que la casilla de verificación esté deshabilitada en Android
- Android: checkbox listener
- Cómo tachar los elementos de texto en listview cuando está marcada?
- OnItemClickListener no funcionó con la casilla de verificación?
- Cómo personalizar (aumentar el tamaño) de la casilla de verificación en Android
- Cómo establecer la casilla de verificación en el lado derecho del texto
Así es como lo hice funcionar:
En primer lugar, necesita una matriz independiente para su estado marcado. Tiene que ser del mismo tamaño que el getCount()
su adaptador getCount()
.
Luego, en su getView, el setOnCheckedChangedListener de su casilla de verificación debe PRECEED sus sentencias checkbox.setChecked.
ejemplo:
holder.checkBox.setOnCheckedChangeListener(new OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { isChecked[position] = isChecked; } }); holder.checkBox.setChecked(isChecked[position]);
Debe establecer el estado CheckedBox fuera de la inicialización de ViewHolder, como el código siguiente:
if (convertView == null) { viewHolder = new ViewHolder(); convertView.setTag(viewHolder); } else { viewHolder = (ViewHolder) convertView.getTag(); } viewHolder.checkedBox.setChecked();
BTW: utiliza SparseBooleanArray en lugar de dos listas para almacenar el estado CheckedBox.
El problema es debido al hecho de que listview recicla las vistas
Así que en el método getView(
)
if (convertView == null) { ........ } else { holder = (ViewHolder) convertView.getTag(); } // Uncheck needed boxes here... You need to implement your logic if( 'position' is checked earlier) holder.check.setChecked(true); else holder.check.setChecked(false);
Es necesario escribir el código para administrar el estado de la vista si el convertidor no es nulo, ya que es una vista ya utilizada que puede estar marcando casillas de verificación.