2010-10-12 6 views
5

J'ai un Android ListView dont les articles ont une case à cocher.CheckBox change la valeur deux fois

La case à cocher est cochée par défaut. Une fois décochée, elle devrait être retirée de la liste.

Le problème est que onCheckedChanged est Licenciement deux fois: quand je tape la case pour la décocher (avec isCheckedfalse) et après je supprimer l'élément (avec isCheckedtrue).

Ceci est le code correspondant de mon 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'est-ce que je fais mal?

+0

Que fait la méthode 'remove()', puisque ce n'est pas une méthode sur ListAdapter'? – CommonsWare

+0

J'utilise un ArrayAdapter. Selon le code source Android, la méthode remove supprime l'élément du tableau et notifie que les données ont été modifiées. – hpique

Répondre

0

Je rencontre le même problème. Après quelques recherches, j'ai découvert qu'il y a un comportement similaire dans RadioGroup pour setCheckChangeListener.

Marquer des choses désordre, semble être un bug.

Ma solution de contournement était de définir la balise à null à la fin de l'auditeur Cela a fonctionné pour moi.

private OnCheckedChangeListener checkBoxitemClickListener = new OnCheckedChangeListener() { 

    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 


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

     buttonView.setTag(null);       
    } 
}; 

Si vous devez mettre à jour votre ListView après, ne pas oublier d'appeler « notifyDataSetChanged » sur votre carte.

Vive

5

je rencontré le même problème, il semble être un bug Android cette exécution deux fois de la méthode onCheckChanged.

Ma solution: mettre en œuvre onClickListener, au lieu de onCheckedChangedListener.

Quelque chose comme ceci:

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

Oui, je pense que l'écoute de onCheckedChange est exagérée et pas la bonne chose à faire dans la plupart des cas. Le problème de base cependant pour moi était d'obtenir la bonne perspective, à savoir, que la vue n'est pas la même que l'objet de données qui est vu. – rwst

2

J'ai eu un problème similaire et juste résolu correctement sans avoir à éviter d'utiliser l'intention OnCheckedChangeListener.

Problème code

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

Remarque J'ai mis la vérification de l'état avant je mets l'auditeur, c'était d'empêcher l'auditeur de tirer sur la création. Mais, l'auditeur a commencé à déclencher l'événement à la vérification exactement deux fois seulement après que l'adaptateur a été forcé à être recréé ou en utilisant notifyDataSetChanged.

Solution

Effacer l'auditeur avant définir l'état de contrôle, même lors de la création ici.

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

Maintenant, aucun écouteur résiduel ne sera déclenché lors du réglage de la valeur initiale de la case à cocher.