2011-01-04 17 views
8

Ich verwende einen angepassten BaseAdapter, um Elemente in einem ListView anzuzeigen. Die Elemente sind nur Zeichenfolgen, die in einer ArrayList gehalten werden.Löschen von Elementen aus einem ListView mit einem benutzerdefinierten BaseAdapter

Die Listenelemente haben eine Löschschaltfläche (großes rotes X), und ich möchte das Element aus der ArrayList entfernen und die ListView benachrichtigen, um sich selbst zu aktualisieren.

Aber jede Implementierung, die ich ausprobiert habe, erhält mysteriöse Positionsnummern, so dass zum Beispiel das Klicken auf den Löschknopf von Element 2 das Element 5 löscht. Es scheint fast völlig zufällig zu sein.

Eine Sache zu beachten ist, dass Elemente wiederholt werden können, aber in der gleichen Reihenfolge gehalten werden müssen. Zum Beispiel kann ich „Irish“ zweimal haben, als Elemente 3 und 7.

Mein Code ist unten:

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; 
} 

Ich versuche später die gelöschten Elements Position abzurufen, indem das Tag greifen, aber es ist immer die falsche Position in der Liste. Es gibt kein auffälliges Muster für die hier gegebene Position, es erscheint immer zufällig.

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

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

    ... 
    ... 
    ... 
} 

Ich würde sehr zufrieden sein, nur das Element aus der Arraylist zu löschen und haben die Listview selbst aktualisieren, aber die Position, die ich bin immer falsch ist, so kann ich das nicht tun.

Bitte beachten Sie, dass ich zunächst den deleteButton clickListener innerhalb der getView-Methode hatte und 'position' verwendet habe, um den Wert zu löschen, aber ich hatte das gleiche Problem.

Alle Vorschläge geschätzt, das ist wirklich irritierend mich.

Antwort

5

Sie müssen die Position jedes Mal einstellen. Ihre Implementierung legt nur die Position für die Erstellung der Ansicht fest. Wenn die Ansicht jedoch wiederverwendet wird (wenn convertView nicht null ist), wird die Position nicht auf den korrekten Wert gesetzt.

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

Brilliant, danke. Ich kann nicht glauben, dass ich so lange mit so einem dummen Problem beschäftigt war. Ich habe meine allgemeine Lösung als separate Antwort für Interessierte hinzugefügt. – HXCaine

0

Sie benötigen OnItemClickListener Schnittstelle zu implementieren, und das Element in der onItemClick Methode löschen, ein Parameter der Methode ist die Position.

+1

er hat eine Schaltfläche, so dass der Zuhörer nicht angemessen sein wird. Dieser Listener funktioniert nur, wenn das gesamte Listenelement das Click-Ereignis empfängt. –

0

Meine letzte Lösung war die akzeptierte Antwort von Greg zu verwenden und die folgenden:

  • Shop die Halter in einer HashMap, mit den Artikelpositionen als Schlüssel (dies so leer im Konstruktor initialisiert)

    private HashMap mHolders;

  • verwenden als OnClickListener Methode:

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(); 
} 

[Bitte geben Sie die seltsame Formatierung entschuldigen. Die Codeeinbettung funktioniert nicht richtig]

Verwandte Themen