2010-10-12 18 views
5

Tengo un Android ListView cuyos elementos tienen una casilla de verificación.CheckBox cambia el valor dos veces

La casilla de verificación está marcada de forma predeterminada. Una vez desactivada, debe eliminarse de la lista.

El problema es que se está onCheckedChanged disparó dos veces: cuando toco la casilla de verificación para desactivarla (con isCheckedfalse) y después se quita el elemento (con isCheckedtrue).

Este es el código correspondiente de mi ArrayAdapter:

public View getView(final int position, View convertView, ViewGroup parent) { 
    ViewHolder holder; 
    if (convertView == null) { 
     convertView = mInflater.inflate(R.layout.item, parent, false); 
     holder = new ViewHolder(); 
     holder.check = (CheckBox) convertView.findViewById(R.id.check); 
     convertView.setTag(holder); 
    } else { 
     holder = (ViewHolder) convertView.getTag(); 
    } 
    final Object item = this.getItem(position); 
    holder.check.setOnCheckedChangeListener(new CheckBox.OnCheckedChangeListener() { 
     @Override 
     public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 
      if (!isChecked) { 
       remove(item); // This somehow calls onCheckedChanged again 
      } 
     } 
    }); 
    return convertView; 
} 

¿Qué estoy haciendo mal?

+0

¿Qué hace el método 'remove()', ya que no es un método en 'ListAdapter'? – CommonsWare

+0

Estoy usando un ArrayAdapter. De acuerdo con el código fuente de Android, el método de eliminación elimina el elemento de la matriz y notifica que los datos se han cambiado. – hpique

Respuesta

0

Me encuentro con el mismo problema.

Después de algunas investigaciones descubrí que hay un comportamiento similar en RadioGroup para setCheckChangeListener.

El etiquetado arruina las cosas, parece un error.

Mi solución fue configurar la etiqueta para anular al final del oyente Me funcionó.

private OnCheckedChangeListener checkBoxitemClickListener = new OnCheckedChangeListener() { 

    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 


     if(isChecked) 
     {    
      //do smth 
     }else 
     { 
      //do smth 
     } 

     buttonView.setTag(null);       
    } 
}; 

Si necesita actualizar su ListView después, no se olvide de llamar "notifyDataSetChanged" en el adaptador.

Saludos

5

me encontré con el mismo problema, que parece ser un error de Android esta ejecución el doble del método onCheckChanged.

Mi solución: implementar onClickListener, en lugar de onCheckedChangedListener.

Algo como esto:

private final class CheckUpdateListener implements OnClickListener { 

    private Group parent; 
    private boolean isChecked; 

    private CheckUpdateListener(Group parent) { 

     this.parent = parent; 

    } 

    @Override 
    public void onClick(View box) { 
     this.isChecked = !parent.isChecked(); 

     parent.setChecked(isChecked); 

     notifyDataSetChanged(); 

    } 

} 
+0

Sí, creo que escuchar enCheckedChange es excesivo y no es lo correcto en la mayoría de los casos. Sin embargo, el problema básico para mí fue obtener la perspectiva correcta, es decir, que la Vista no es lo mismo que el objeto de datos que se visualiza. – rwst

2

tuve un problema similar y acaba de resolver correctamente sin tener que evitar el uso de la OnCheckedChangeListener previsto.

código de problema

holder.someCheckBox.setChecked(false); 
holder.someCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 
    @Override 
    public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { 
     ... 
    } 
}); 

Nota que establece el estado de comprobación antes de fijo el oyente, esto fue para evitar que el detector a disparar sobre la creación.

Pero, el oyente comenzó a disparar el evento on-check exactamente dos veces solo después de que el adaptador se forzó a volver a crearse o mediante el uso de notifyDataSetChanged.

Solución

Borrar el oyente antes de establecer el estado de comprobación, incluso durante la creación aquí.

holder.someCheckBox.setOnCheckedChangeListener(null); 
holder.someCheckBox.setChecked(false); 
holder.someCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 
    @Override 
    public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { 
     ... 
    } 
}); 

Ahora cualquier detector residual no se disparará cuando se establece el valor inicial de la casilla de verificación.

Cuestiones relacionadas