2011-01-04 1 views
8

J'utilise un BaseAdapter personnalisé pour afficher des éléments sur un ListView. Les éléments sont juste des chaînes contenues dans une ArrayList.Suppression d'éléments d'un ListView à l'aide d'un BaseAdapter personnalisé

Les éléments de la liste ont un bouton de suppression sur eux (grand rouge X), et je voudrais supprimer l'élément de la liste de tableaux, et notifier le ListView pour se mettre à jour. Cependant, chaque implémentation que j'ai essayée obtient des numéros de position mystérieux, par exemple si je clique sur le bouton Supprimer de l'élément 2, je supprime l'item 5. Il semble être presque entièrement aléatoire. Une chose à noter est que les éléments peuvent être répétés, mais doivent être conservés dans le même ordre. Par exemple, je peux avoir « Irlandais » deux fois, comme des éléments 3 et 7.

Mon code est ci-dessous:

private static class ViewHolder { 
     TextView lang; 
     int position; 
} 

public View getView(final int position, View convertView, ViewGroup parent) { 
    ViewHolder holder; 
    if (convertView == null) { 
     convertView = mInflater.inflate(R.layout.language_link_row, null); 
     holder = new ViewHolder(); 
     holder.lang = (TextView)convertView.findViewById(R.id.language_link_text); 
     holder.position = position; 

     final ImageView deleteButton = (ImageView) 
       convertView.findViewById(R.id.language_link_cross_delete); 
     deleteButton.setOnClickListener(this); 

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

    holder.lang.setText(mLanguages.get(position)); 

    return convertView; 
} 

je tente plus tard pour récupérer la position de l'élément supprimé en saisissant l'étiquette, mais il est toujours la mauvaise position dans la liste. Il n'y a pas de motif notable à la position donnée ici, cela semble toujours aléatoire.

// The delete button's listener 
public void onClick(View v) { 

    ViewHolder deleteHolder = (ViewHolder) v.getTag(); 
    int pos = deleteHolder.position; 

    ... 
    ... 
    ... 
} 

Je serais très heureux de simplement supprimer l'élément de la ArrayList et ont le ListView se mettre à jour, mais la position que je reçois est incorrect, je ne peux pas le faire.

Veuillez noter que j'ai d'abord eu le deleteButton clickListener dans la méthode getView, et utilisé 'position' pour supprimer la valeur, mais j'ai eu le même problème.

Toute suggestion appréciée, c'est vraiment irritant pour moi.

Répondre

5

Vous devez définir la position à chaque fois. Votre implémentation définit uniquement la position sur la création de la vue. Cependant, lorsque la vue est recyclée (lorsque convertView n'est pas nul), la position ne sera pas définie sur la valeur correcte.

public View getView(final int position, View convertView, ViewGroup parent) { 
    ViewHolder holder; 
    if (convertView == null) { 
     convertView = mInflater.inflate(R.layout.language_link_row, null); 
     holder = new ViewHolder(); 
     holder.lang = (TextView)convertView.findViewById(R.id.language_link_text); 

     final ImageView deleteButton = (ImageView) 
       convertView.findViewById(R.id.language_link_cross_delete); 
     deleteButton.setOnClickListener(this); 

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

    holder.lang.setText(mLanguages.get(position)); 
    holder.position = position; 
    return convertView; 
} 
+1

Génial, merci. Je ne peux pas croire que j'ai passé si longtemps sur un problème aussi stupide. J'ai ajouté ma solution générale comme réponse séparée pour ceux qui sont intéressés. – HXCaine

0

vous devez implémenter l'interface OnItemClickListener, et supprimer l'élément dans la méthode onItemClick, un paramètre de la méthode est la position.

+1

il a un bouton, de sorte que l'écouteur ne sera pas approprié. Cet écouteur ne fonctionne que si l'élément entier de la liste reçoit l'événement click. –

0

Ma solution finale était d'utiliser la réponse acceptée par Greg et les éléments suivants:

  • Conserver les supports dans un HashMap, avec les positions de l'élément que les touches (ce qui est initialisée comme vide dans le constructeur)

    private HashMap mHolders;

  • utiliser comme la méthode onClickListener:

public void onClick(View v) { 
    ViewHolder deleteHolder = (ViewHolder) v.getTag(); 
    int pos = deleteHolder.position; 
    mHolders.remove(pos);

ViewHolder currentHolder; 

    // Shift 'position' of remaining languages 
    // down since 'pos' was deleted 
    for(int i=pos+1; i<getCount(); i++){ 
     currentHolder = mHolders.get(i); 
     currentHolder.position = i-1; 
    } 
    mLanguages.remove(pos); 
    notifyDataSetChanged(); 
} 

[S'il vous plaît excuser la mise en forme bizarre. L'intégration de code ne fonctionne pas correctement]

Questions connexes