2010-09-01 14 views
0

J'ai une ListActivity qui utilisait initialement un ArrayAdapter. Chaque élément de ma ListView contient une case à cocher.Jeu "Whack a checkbox" avec ListView

J'ai changé Adapters en un CursorAdapter. Tout fonctionne correctement sauf les cases à cocher sont hors de contrôle. Par exemple: Lorsque je clique sur la case à cocher en position 1, la case à cocher en position 4 est vérifiée. Si je coche à nouveau la case 1, elle vérifie (ie: Quand je coche la case en position 1, si la case en case 4 n'est pas cochée, la case à cocher en position 4 sera cochée, sinon, la case à cocher en position 1 est cochée). Décocher les cases ne semble pas montrer de comportement bizarre. Des idées pourquoi?

Mise à jour: Cochez la case en arrière en fonction du nombre d'éléments affichés à l'écran. Ce que je veux dire est, s'il y a 5 éléments visibles, en cliquant sur le 1er vérifiera le 5ème, en cliquant sur le 2ème avec vérifier le 4ème, en cliquant sur le 3ème vérifiera le 3ème. De plus, une fois qu'on a vérifié, ils commencent tous à bien se comporter.

Apparemment, commentant ce fait disparaître le problème:

if (holder.chkSelect != null) { 
     holder.chkSelect.setOnCheckedChangeListener(this); 
    } 

Cela a certainement quelque chose à voir avec showMultiPanel sauter vers le haut et peut-être réduire le nombre de lignes qui peuvent être vus. Bien que je ne comprends pas pourquoi cela a bien fonctionné avec un ArrayAdapter.

Voici une copie de mon CursorAdapter

public class InboxAdapter extends CursorAdapter implements CheckBox.OnCheckedChangeListener { 
    private int mCheckedCount = 0; 

    public InboxAdapter(Context context, Cursor c) { 
     super(context, c); 
    } 

    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 
     if (buttonView.getId() == R.id.inbox_itemcheck) { 
      if (isChecked) { 
       mCheckedCount++; 
      } 
      else { 
       mCheckedCount--; 
      } 
      ActivityInbox.this.showMultiPanel((mCheckedCount > 0) ? true : false); 
     } 
    } 

    @Override 
    public void bindView(View view, Context context, Cursor cursor) { 
     InboxHolder holder = (InboxHolder)view.getTag(); 

     if (holder.txtDate != null) { 
      DateFormat df = new SimpleDateFormat("MM/dd/yyyy"); 
      Date d = new Date(cursor.getInt(cursor.getColumnIndex("created_on")) * 1000L); 
      holder.txtDate.setText(df.format(d)); 
     } 
     if (holder.txtSubject != null) { 
      holder.txtSubject.setText(cursor.getString(cursor.getColumnIndex("subject"))); 
      if (cursor.getInt(cursor.getColumnIndex("read")) == 0) { 
       holder.txtSubject.setTypeface(null, Typeface.BOLD); 
      } 
      else { 
       holder.txtSubject.setTypeface(null, Typeface.NORMAL); 
      } 
     } 

     if(holder.txtSummary != null) { 
      holder.txtSummary.setText(cursor.getString(cursor.getColumnIndex("summary"))); 
     } 

     if (cursor.getInt(cursor.getColumnIndex("read")) == 0) { 
      view.setBackgroundResource(R.drawable.selector_inbox_unread); 
     } 
     else { 
      view.setBackgroundResource(R.drawable.selector_inbox_read); 
     } 

     if (holder.lMessageType != null) { 
      if (cursor.getInt(cursor.getColumnIndex("read")) == 0) { 
       holder.lMessageType.setVisibility(View.VISIBLE); 
      } 
      else { 
       holder.lMessageType.setVisibility(View.INVISIBLE); 
      } 
     } 
    } 

    @Override 
    public View newView(Context context, Cursor cursor, ViewGroup parent) { 
     LayoutInflater inflater = LayoutInflater.from(context); 
     View v = inflater.inflate(R.layout.layout_inbox_item, parent, false); 

     InboxHolder holder = new InboxHolder(); 
     holder.txtDate = (TextView) v.findViewById(R.id.inbox_item_date); 
     holder.txtSubject = (TextView) v.findViewById(R.id.inbox_item_subject); 
     holder.txtSummary = (TextView) v.findViewById(R.id.inbox_item_summary); 
     holder.chkSelect = (CheckBox) v.findViewById(R.id.inbox_itemcheck); 
     holder.lMessageType = (LinearLayout) v.findViewById(R.id.inbox_messagetype); 

     v.setTag(holder); 

     if (holder.chkSelect != null) { 
      holder.chkSelect.setOnCheckedChangeListener(this); 
     } 
     return v; 
    } 

}

+0

Bonjour! J'ai le même problème en utilisant l'adaptateur de tableau. Puis-je savoir si vous l'avez réparé et comment? Merci – exception01

Répondre

0

Notez qu'un ListView peut réutiliser un seul View pour plus d'une ligne de la table, et il est à l'adaptateur pour décider si Cela arrive. Je crois que CursorAdapter est configuré pour le faire lorsque cela est possible en regroupant les instances de vue et en créant seulement assez pour construire l'écran.

Pour une solution simple pour une liste restreinte, il suffit de coller avec un ArrayAdapter et de lire toutes les données à l'avance. Cela évite tout le problème.

Si vous voulez rester avec CursorAdapter, vous devez stocker les états vérifiés vous-même. Une façon serait de garder un HashSet des ID qui sont vérifiés. Dans votre case à cocher, cliquez sur écouteur, mettez-le à jour en ajoutant ou en supprimant l'identifiant de cette ligne dans l'ensemble. Dans bindView, définissez l'état de la case à cocher en fonction de l'ID de la ligne dans la carte. Vous pouvez également définir l'écouteur dans bindView, où vous pouvez définir une variable locale final sur l'ID et utiliser cette valeur dans le code de l'écouteur.

+0

Merci pour votre réponse. Il semble que je n'ai pas accès au contexte de l'activité dans getView? newView et bindView le transmettent, pas getView. getContext() est indéfini. – Andrew

+0

J'essaie d'utiliser parent.getContext() – Andrew

+0

J'ai remplacé getView() et ai newView() retournant null. Le même problème se produit. Je pense que cela a quelque chose à voir avec showMultiPanel. showMultiPanel est une fonction qui anime une petite fenêtre en bas de l'écran (exactement la même que l'application Android Mail lorsque vous cochez une case). Lorsque le panneau montre, le nombre d'éléments visibles dans la liste diminue de 1. Pour une raison quelconque, je pense que cela jette l'adaptateur une courbe. Fonctionne bien pour ArrayAdapters si ... – Andrew