studio solo seleccionar propiedades personalizar checklist android listview checkbox

android - solo - Al desplazarse por ListView personalizado, el valor de la casilla de verificación cambia



propiedades checkbox android (8)


Lo que tengo: una vista de lista personalizada con Textviews y casilla de verificación.

Problema: supongamos que mi pantalla puede mostrar solo 6 elementos de la lista al tiempo, y los otros son invisibles. Así que revisé el primer elemento de la lista (elemento en la posición 0). Me desplazo hacia abajo para ver toda mi lista, cuando me desplazo hacia arriba en el primer elemento (elemento en la posición 0) la casilla de verificación se marca correctamente. ¡Estupendo! Pero ahora hay nuevos elementos que también se revisan, por ejemplo, el artículo en la posición 8 (porque cuando me desplazo por la lista (para el Ric), se convierte en el nuevo elemento en la posición 0..recuerdo que mi pantalla muestra solo 7 elementos a la vez). Y se verifica, ¡pero nunca lo he comprobado!
Pregunta : ¿Cómo puedo evitar este problema? No quiero que la casilla en la que no hago clic cambie su estado. Debajo de mi adaptador para listView con la función getView donde he implementado el setOnCheckedChangeListener:

public class NewQAAdapterSelectFriends extends BaseAdapter { private LayoutInflater mInflater; private Person[] data; public NewQAAdapterSelectFriends(Context context) { mInflater = LayoutInflater.from(context); } public void setData(Person[] data) { this.data = data; } @Override public int getCount() { return data.length; } @Override public Object getItem(int item) { return data[item]; } @Override public long getItemId(int position) { return position; } @Override public View getView(final int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = mInflater.inflate(R.layout.item_select_friends, null); final ViewHolder viewHolder = new ViewHolder(); viewHolder.nameText=(TextView) convertView.findViewById(R.id.personName); viewHolder.surnameText=(TextView) convertView.findViewById(R.id.personSurname); viewHolder.contactImage=(ImageView) convertView.findViewById(R.id.personImage); viewHolder.checkBox=(CheckBox)convertView.findViewById(R.id.checkBox); convertView.setTag(viewHolder); viewHolder.nameText.setTag(viewHolder.nameText); viewHolder.nameText.setTag(viewHolder.surnameText); viewHolder.contactImage.setTag(data[position]); viewHolder.checkBox.setOnCheckedChangeListener( new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) { Person element = (Person) viewHolder.checkBox.getTag(); if(isChecked){ element.setCheck(buttonView.isChecked()); //data[position].setCheck(true); //this is equivalent to previous line } else{ //to-do } } }); viewHolder.checkBox.setTag(data[position]); } else { } ViewHolder holder = (ViewHolder) convertView.getTag(); holder.nameText.setText(data[position].getName()); holder.surnameText.setText(data[position].getSurname()); holder.contactImage.setImageResource(data[position].getPhotoRes()); holder.contactImage.setScaleType(ScaleType.FIT_XY); holder.checkBox.setChecked(data[position].isCheck()); return convertView; } static class ViewHolder { TextView nameText; TextView surnameText; ImageView contactImage; CheckBox checkBox; } }

Gracias por las respuestas :)

EDITAR: con la sugerencia cambié mi getView como a continuación:

@Override public View getView(final int position, View convertView, ViewGroup parent) { final ViewHolder viewHolder; if (convertView == null) { convertView = mInflater.inflate(R.layout.item_select_friends, null); viewHolder=new ViewHolder(); viewHolder.nameText=(TextView) convertView.findViewById(R.id.personName); viewHolder.surnameText=(TextView) convertView.findViewById(R.id.personSurname); viewHolder.contactImage=(ImageView) convertView.findViewById(R.id.personImage); viewHolder.checkBox=(CheckBox)convertView.findViewById(R.id.checkBox); convertView.setTag(viewHolder); viewHolder.nameText.setTag(viewHolder.nameText); viewHolder.nameText.setTag(viewHolder.surnameText); viewHolder.contactImage.setTag(data[position]); viewHolder.checkBox.setChecked(data[position].isCheck()); viewHolder.checkBox.setOnClickListener(new OnClickListener() { public void onClick(View arg0) { if(viewHolder.checkBox.isChecked()==true) data[position].setCheck(true); else data[position].setCheck(false); } }); } else{ viewHolder = (ViewHolder) convertView.getTag(); } viewHolder.nameText.setText(data[position].getName()); viewHolder.surnameText.setText(data[position].getSurname()); viewHolder.contactImage.setImageResource(data[position].getPhotoRes()); viewHolder.contactImage.setScaleType(ScaleType.FIT_XY); viewHolder.checkBox.setChecked(data[position].isCheck()); return convertView; }

SITUACIÓN DESPUÉS DE EDITAR: Ahora, si reviso los elementos iniciales que se muestran en la pantalla y luego selecciono la lista, su valor se guarda correctamente. Pero cuando me desplazo por la lista y, por ejemplo, quiero verificar las últimas casillas de verificación de mi lista, luego, cuando me desplazo, se desmarcan ... PERO ¿POR QUÉ ??????

RESUELTO : resolví mi problema de getView con este código:

public class NewQAAdapterSelectFriends extends BaseAdapter { private LayoutInflater mInflater; private Person[] data; boolean[] checkBoxState; ViewHolder viewHolder; public NewQAAdapterSelectFriends(Context context) { mInflater = LayoutInflater.from(context); } public void setData(Person[] data) { this.data = data; checkBoxState=new boolean[data.length]; } @Override public int getCount() { return data.length; } @Override public Object getItem(int item) { return data[item]; } @Override public long getItemId(int position) { return position; } @Override public View getView(final int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = mInflater.inflate(R.layout.item_select_friends, null); viewHolder=new ViewHolder(); viewHolder.nameText=(TextView) convertView.findViewById(R.id.personName); viewHolder.surnameText=(TextView) convertView.findViewById(R.id.personSurname); viewHolder.contactImage=(ImageView) convertView.findViewById(R.id.personImage); viewHolder.checkBox=(CheckBox)convertView.findViewById(R.id.checkBox); convertView.setTag(viewHolder); } else{ viewHolder = (ViewHolder) convertView.getTag(); } viewHolder.nameText.setText(data[position].getName()); viewHolder.surnameText.setText(data[position].getSurname()); viewHolder.contactImage.setImageResource(data[position].getPhotoRes()); viewHolder.contactImage.setScaleType(ScaleType.FIT_XY); viewHolder.checkBox.setChecked(checkBoxState[position]); viewHolder.checkBox.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { if(((CheckBox)v).isChecked()){ checkBoxState[position]=true; data[position].setCheck(true); }else{ checkBoxState[position]=false; data[position].setCheck(false); } } }); return convertView; } static class ViewHolder { TextView nameText; TextView surnameText; ImageView contactImage; CheckBox checkBox; }

}

He visto este tutorial para hacer mi getView: http://androidcocktail.blogspot.it/2012/04/adding-checkboxes-to-custom-listview-in.html


Debe actualizar el adaptador para conservar el valor de la casilla de verificación

holder.chk.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { CheckBox c = (CheckBox)v.findViewById(R.id.chkID); Boolean chk = c.isChecked(); Integer pos = (Integer)v.getTag(); itemList.get(pos).setChk(chk); } });

Para obtener más ayuda, puede consultar esta publicación en el valor Conservar casilla de verificación


Está configurando la etiqueta de la casilla solo si convertview es nulo. Esto sucede solo para la primera pantalla de registros. Cuando el usuario se desplaza hacia abajo, las conversviews anteriores se reciclan. Por lo tanto, sus casillas de verificación tienen elementos de datos más antiguos como sus etiquetas.

Su oyente de cambio verificado debería verse así:

new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) { Person element = (Person) viewHolder.checkBox.getTag(); data[position].setCheck(isChecked); if(isChecked) { // do your stuff } else { //to-do } } }


No cubrió el caso convertView! = Null, esto es lo que sucede cuando se desplaza hacia arriba y hacia abajo. Debería implementar una forma de reciclar el convertView (mejor) o simplemente ignorarlo y dar una Vista nueva en este caso también (peor).


Resolví mi problema simplemente cambiando el "setOnCheckedChangeListener" por "setOnClickListener"

public View getView(final int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { CheckBox cbItemChecklist = new CheckBox(context); holder = new ViewHolder(); holder.cbItemChecklist = cbItemChecklist; convertView = cbItemChecklist; convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } final ItemChecklist itemChecklist = itensChecklist.get(position); holder.cbItemChecklist.setText(itemChecklist .getDescricaoItemChecklist()); holder.cbItemChecklist.setChecked(itemChecklist.isChecked()); holder.cbItemChecklist .setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if(itemChecklist.isChecked()){ itemChecklist.setChecked(false); } else { itemChecklist.setChecked(true); } } }); return convertView; }


Tengo una buena alternativa para un CheckBox. Puedes usar android:state_activated="true" para tus filas de ListView. No pierde su estado y no requiere mucho código.

Aquí es cómo funciona

  • crea active_row.xml en tu carpeta active_row.xml


<selector xmlns:android="http://schemas.android.com/apk/res/android">

<item android:state_activated="true" android:drawable="@android:color/darker_gray"/> </selector>

  • Establezca el fondo de su diseño de fila como android:background="@drawable/active_row.xml"
  • Y finalmente agregue esto a su ListView android:choiceMode="multipleChoice"

Puede verificar el estado de cada fila como esta

View v; LinearLayout yourRowLayout; for (int i = 0; i < yourListView.getChildCount(); i++) { v = yourListView.getChildAt(i); yourRowLayout = (LinearLayout) v.findViewById(R.id. yourRowLayout); if(yourRowLayout.isActivated()){.... } }



Verifica el código a continuación -

public View getView(int position, View convertView, ViewGroup parent){ View view = convertView; ViewHolder holder = new ViewHolder(); if(view == null){ view = inflater.inflate(R.layout.list_callcycle_blue, null); holder.llContainer = (LinearLayout) view.findViewById(R.id.ll_container); holder.lblLabel = (TextView) view.findViewById(R.id.txt_desc); holder.cb = (CheckBox) view.findViewById(R.id.cb_store); view.setTag(holder); } else { holder = (ViewHolder) view.getTag(); } final Object data = getItem(position); holder.lblLabel.setText(data.getDescription()); holder.cb.setTag(position); holder.cb.setOnCheckedChangeListener(new OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { int position = (Integer) buttonView.getTag(); objects.get(position).setChecked(buttonView.isChecked()); } }); holder.cb.setChecked(isChecked(position)); return view; }

Siempre tenga en cuenta, utilice change holder.cb.setOnCheckedChangeListener() es decir, cualquier oyente antes de establecer los datos, en nuestro caso es holder.cb.setChecked()

Motivo: cuando nos desplazamos, listview reciclará las vistas, de modo que si setchecked se usa antes que los oyentes, elegirá valores basándose en el viejo oyente. Y si lo configuramos después del oyente, entonces tomará los últimos valores


revisa este código

public class NewQAAdapterSelectFriends extends BaseAdapter { private LayoutInflater mInflater; private Person[] data; ArrayList<String> checkedItem=new ArrayList<String>(); public NewQAAdapterSelectFriends(Context context) { mInflater = LayoutInflater.from(context); } public void setData(Person[] data) { this.data = data; } @Override public int getCount() { return data.length; } @Override public Object getItem(int item) { return data[item]; } @Override public long getItemId(int position) { return position; } @Override public View getView(final int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = mInflater.inflate(R.layout.item_select_friends, null); final ViewHolder viewHolder = new ViewHolder(); viewHolder.nameText=(TextView) convertView.findViewById(R.id.personName); viewHolder.surnameText=(TextView) convertView.findViewById(R.id.personSurname); viewHolder.contactImage=(ImageView) convertView.findViewById(R.id.personImage); viewHolder.checkBox=(CheckBox)convertView.findViewById(R.id.checkBox); convertView.setTag(viewHolder); viewHolder.nameText.setTag(viewHolder.nameText); viewHolder.nameText.setTag(viewHolder.surnameText); viewHolder.contactImage.setTag(data[position]); viewHolder.checkBox.setOnCheckedChangeListener( new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) { Person element = (Person) viewHolder.checkBox.getTag(); if(isChecked){ getCheckList(data[position],isChecked); } else{ getCheckList(data[position],isChecked); } } }); viewHolder.checkBox.setTag(data[position]); } ViewHolder holder = (ViewHolder) convertView.getTag(); holder.nameText.setText(data[position].getName()); holder.surnameText.setText(data[position].getSurname()); holder.contactImage.setImageResource(data[position].getPhotoRes()); holder.contactImage.setScaleType(ScaleType.FIT_XY); if(checkedItem != null && checkedItem.contains(data[position])){ viewHolder.checkBox.setChecked(true); }else { viewHolder.checkBox.setChecked(false); } return convertView; } static class ViewHolder { TextView nameText; TextView surnameText; ImageView contactImage; CheckBox checkBox; } public void getCheckList(String value,boolean status){ if(!checkedItem.contains(value) && status) { checkedItem.add(value); } if(checkedItem.contains(value) && !status) { checkedItem.remove(value); } } }