PDA

Ver la Versión Completa : Problema listview con checkboxes


rafaxplayer
14/09/13, 18:37:12
Saludos compañeros , tengo un problema con un listview con custom adapter y checkboxes , el problema básicamente es que al hacer visibles o checkar los checks que están fuera de de la lista al hacer scroll y re-dibujarlos se comportan como quieren , los seleccionados se de-seleccionan y algunos visibles se hace invisibles...
utlizo unos métodos para hacer los check visibles y para checkarlos todos o no , serian estos:

private void setListChecksVisibles(boolean isVisible) {
int nVisible = isVisible ? View.VISIBLE : View.GONE;
header.setVisibility(nVisible);
footer.setVisibility(nVisible);
for(int i=0; i<lst.getChildCount(); i++){
View ll = lst.getChildAt(i);
CheckBox cb = (CheckBox) ll.findViewById(R.id.checkItems);
cb.setVisibility(nVisible);

}
adp.notifyDataSetChanged();
}

private void checkAll(boolean bCheck) {
for(int i=0; i<lst.getChildCount(); i++){
View ll =lst.getChildAt(i);
CheckBox cb = (CheckBox)ll.findViewById(R.id.checkItems);
cb.setChecked(bCheck);

}
adp.notifyDataSetChanged();
}

He probado en el adapter ah crear un array de booleanos para guardar los cambios en los checkboxes y actualizarlos en el getview , pero no me esta dando ningún resultado.

mi adapter es este:

public class HistoryAdapter extends BaseAdapter {
private LayoutInflater mInflater = null;
private Cursor cur;
private ArrayList<Boolean> itemSelection;

public HistoryAdapter(){
db = new DBHelper(getApplicationContext(), DBHelper.TABLE_NAME, null, 1);
this.cur = db.SelectAll();
mInflater = (LayoutInflater)getApplicationContext().getSystemS ervice(Activity.LAYOUT_INFLATER_SERVICE);
itemSelection= new ArrayList<Boolean>();
for(int i=0;i<this.getCount();i++) {
itemSelection.add(i, false);
}
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return cur.getCount();
}

@Override
public Cursor getItem(int position) {

cur.moveToPosition(position);
return cur;
}

@Override
public long getItemId(int position) {

Cursor c = getItem(position);
long id =(Long)(long)c.getInt(c.getColumnIndex(DBHelper.KE Y_ID));
return id;
}


private class ViewHolder {

TextView lng;
TextView lat;
TextView date;
CheckBox ch;

}

@Override
public View getView(final int position, View convertView, ViewGroup arg2) {


ViewHolder holder= null;
holder= new ViewHolder();
if (convertView == null) {
convertView = mInflater.inflate(R.layout.itemhistory, null);
holder.lng = (TextView) convertView.findViewById(R.id.textLongitude);
holder.lat=(TextView) convertView.findViewById(R.id.textLatitude);
holder.date=(TextView) convertView.findViewById(R.id.textDate);
holder.ch=(CheckBox)convertView.findViewById(R.id. checkItems);
holder.ch.setOnCheckedChangeListener(new OnCheckedChangeListener() {

@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
itemSelection.set(position,isChecked);

}
});
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
try
{
Cursor rowItem = getItem(position);


holder.lng.setText(rowItem.getString(rowItem.getCo lumnIndex(DBHelper.KEY_LONGITUDE))+" ");
holder.lat.setText(rowItem.getString(rowItem.getCo lumnIndex(DBHelper.KEY_LATITUDE))+" ");
holder.date.setText(rowItem.getString(rowItem.getC olumnIndex(DBHelper.KEY_DATE))+" ");
holder.ch.setChecked(itemSelection.get(position));
}catch(Exception ex){
ex.printStackTrace();
}

return convertView;

}


}

Alguna sugerencia? gracias de antemano ;)

kriogeN
14/09/13, 19:19:39
Para el setListChecksVisibles debería funcionar, porque no veo en el getView ningún código que modifique la visibilidad de los elementos. Y el reciclado de vista no debería influir, porque estás haciéndolo sobre todos los elementos (aunque realmente sea sobre los elementos visibles todo el tiempo).

Para el checkAll es lógico que no funcione, porque al scrollear y ejecutarse el getView el estado del check depende de itemSelection.get(position), y por tanto se marca según lo que dice ese ArrayList.

La solución para el checkAll es poner todos los elementos de itemSelection al estado que pasas por parámetro.

Para el otro caso, prueba añadiendo en el getView que la visibilidad dependa de una variable booleana en el HistoryAdapter. Y en el método setListChecksVisibles establece esa variable al valor que pasas por parámetro.

rafaxplayer
14/09/13, 21:01:23
Gracias kriogen , he logrado solucionar lo de mostrar y checkar o no todos los checks , lo conseguido usando unos métodos dentro del adapter(setCheckedall(boolean check) , setVisibleChecks(int vis) ) .
Mi problema es ahora la persistencia cuando hago selección aleatoria de los checks , cuando los oculta el scroll y vuelven cambian de estado como le da la gana ;(

he puesto un checkedchangedlistener para editar el array donde guardo el estado para aplicarlo al redibujar pero no funciona, ademas como veras en el listener hay un log.d que me da estado y posicion y por lo que veo la posición no cuadra cuando los items salen de ocultos en el scroll, no se que hago mal en este sentido;(

El adapter:

public class HistoryAdapter extends BaseAdapter {
private LayoutInflater mInflater = null;
private Cursor cur;
private ArrayList<Boolean> itemSelection;
private ArrayList<Integer> itemVisible;
public HistoryAdapter(){
db = new DBHelper(getApplicationContext(), DBHelper.TABLE_NAME, null, 1);
this.cur = db.SelectAll();

mInflater = (LayoutInflater)getApplicationContext().getSystemS ervice(Activity.LAYOUT_INFLATER_SERVICE);
itemSelection=new ArrayList<Boolean>();
for(int i=0 ;i<this.getCount();i++ ) {
itemSelection.add(i, false);
}
itemVisible=new ArrayList<Integer>();
for(int i=0 ;i<this.getCount();i++ ) {
itemVisible.add(i, View.GONE);
}
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return cur.getCount();
}

@Override
public Cursor getItem(int position) {

cur.moveToPosition(position);
return cur;
}

@Override
public long getItemId(int position) {

Cursor c = getItem(position);
long id =(Long)(long)c.getInt(c.getColumnIndex(DBHelper.KE Y_ID));
return id;
}

public void setCheckedall(boolean check) {
for(int i=0 ;i<itemSelection.size();i++ ) {
itemSelection.set(i,check);
}
this.notifyDataSetChanged();
}

public void setVisibleChecks(int vis) {
for(int i=0 ;i<itemVisible.size();i++ ) {
itemVisible.set(i, vis);
}
this.notifyDataSetChanged();
}

private class ViewHolder {

TextView lng;
TextView lat;
TextView date;
CheckBox ch;

}

@Override
public View getView(final int position, View convertView, ViewGroup arg2) {


ViewHolder holder= null;

if (convertView == null) {
holder= new ViewHolder();
convertView = mInflater.inflate(R.layout.itemhistory, null);
holder.lng = (TextView) convertView.findViewById(R.id.textLongitude);
holder.lat=(TextView) convertView.findViewById(R.id.textLatitude);
holder.date=(TextView) convertView.findViewById(R.id.textDate);
holder.ch=(CheckBox)convertView.findViewById(R.id. checkItems);
holder.ch.setOnCheckedChangeListener(new OnCheckedChangeListener() {

@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// TODO Auto-generated method stub
itemSelection.set(position,isChecked);
Log.d("Position",String.valueOf(position)+" "+String.valueOf(isChecked));

}
});
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
try
{
Cursor rowItem = getItem(position);


holder.lng.setText(rowItem.getString(rowItem.getCo lumnIndex(DBHelper.KEY_LONGITUDE))+" ");
holder.lat.setText(rowItem.getString(rowItem.getCo lumnIndex(DBHelper.KEY_LATITUDE))+" ");
holder.date.setText(rowItem.getString(rowItem.getC olumnIndex(DBHelper.KEY_DATE))+" ");
holder.ch.setChecked(itemSelection.get(position));
holder.ch.setVisibility(itemVisible.get(position)) ;
}catch(Exception ex){
ex.printStackTrace();
}

return convertView;

}


}

rafaxplayer
15/09/13, 12:34:05
Bueno arreglado , al final el evento checkedchangued no estaba funcionando bien guardando los cambios , lo ha cambiado por clicklistener y declarado despues:

asi ha quedado el adapter:

public class HistoryAdapter extends BaseAdapter {
private LayoutInflater mInflater = null;
private Cursor cur;
private ArrayList<Boolean> itemSelection;
private ArrayList<Integer> itemVisible;
public HistoryAdapter(){
db = new DBHelper(getApplicationContext(), DBHelper.TABLE_NAME, null, 1);
this.cur = db.SelectAll();

mInflater = (LayoutInflater)getApplicationContext().getSystemS ervice(Activity.LAYOUT_INFLATER_SERVICE);
itemSelection=new ArrayList<Boolean>();
for(int i=0 ;i<this.getCount();i++ ) {
itemSelection.add(i, false);
}
itemVisible=new ArrayList<Integer>();
for(int i=0 ;i<this.getCount();i++ ) {
itemVisible.add(i, View.GONE);
}
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return cur.getCount();
}

@Override
public Cursor getItem(int position) {

cur.moveToPosition(position);
return cur;
}

@Override
public long getItemId(int position) {

Cursor c = getItem(position);
long id =(Long)(long)c.getInt(c.getColumnIndex(DBHelper.KE Y_ID));
return id;
}

public void setCheckedall(boolean check) {
for(int i=0 ;i<itemSelection.size();i++ ) {
itemSelection.set(i,check);
}
this.notifyDataSetChanged();
}

public void setVisibleChecks(int vis) {
for(int i=0 ;i<itemVisible.size();i++ ) {
itemVisible.set(i, vis);
}
this.notifyDataSetChanged();
}

private class ViewHolder {

TextView lng;
TextView lat;
TextView date;
CheckBox ch;

}

@Override
public View getView(final int position, View convertView, ViewGroup arg2) {


ViewHolder holder= null;

if (convertView == null) {
holder= new ViewHolder();
convertView = mInflater.inflate(R.layout.itemhistory, null);
holder.lng = (TextView) convertView.findViewById(R.id.textLongitude);
holder.lat=(TextView) convertView.findViewById(R.id.textLatitude);
holder.date=(TextView) convertView.findViewById(R.id.textDate);
holder.ch=(CheckBox)convertView.findViewById(R.id. checkItems);

convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}

try
{
Cursor rowItem = getItem(position);


holder.lng.setText(rowItem.getString(rowItem.getCo lumnIndex(DBHelper.KEY_LONGITUDE))+" ");
holder.lat.setText(rowItem.getString(rowItem.getCo lumnIndex(DBHelper.KEY_LATITUDE))+" ");
holder.date.setText(rowItem.getString(rowItem.getC olumnIndex(DBHelper.KEY_DATE))+" ");
holder.ch.setChecked(itemSelection.get(position));
holder.ch.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {

itemSelection.set(position, ((CheckBox) v).isChecked());

}
});
holder.ch.setVisibility(itemVisible.get(position)) ;
//holder.ch.setTag(position);
}catch(Exception ex){
ex.printStackTrace();
}

return convertView;

}