2011-01-04 2 views
8

Sto utilizzando un BaseAdapter personalizzato per visualizzare gli elementi su un ListView. Gli elementi sono solo stringhe contenute in un ArrayList.Eliminazione di elementi da un ListView utilizzando un BaseAdapter personalizzato

Le voci di elenco hanno un pulsante di eliminazione su di esse (grande X rossa) e vorrei rimuovere l'elemento da ArrayList e notificare a ListView di aggiornarsi.

Tuttavia, ogni implementazione che ho provato ottiene numeri di posizione misteriosi dati ad esso, quindi per esempio facendo clic sul pulsante di eliminazione del secondo elemento si cancellerà l'elemento 5. Sembra essere quasi del tutto casuale.

Una cosa da notare è che gli elementi possono essere ripetuti, ma devono essere mantenuti nello stesso ordine. Ad esempio, posso avere "irlandese" due volte, come elementi 3 e 7.

Il mio codice è qui sotto:

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

ho poi tentativo di recuperare la posizione dell'elemento cancellato afferrando il tag, ma è sempre la posizione sbagliata nella lista. Non c'è un modello evidente nella posizione qui indicata, sembra sempre casuale.

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

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

    ... 
    ... 
    ... 
} 

sarei molto felice di eliminare solo l'elemento dalla ArrayList e hanno il ListView aggiornarsi, ma la posizione mi sto non è corretta, quindi non posso farlo.

Si prega di notare che ho fatto, in un primo momento, hanno il deleteButton clickListener all'interno del metodo GetView, e 'la posizione' utilizzato per eliminare il valore, ma ho avuto lo stesso problema.

Qualsiasi suggerimento apprezzato, questo mi irrita molto.

risposta

5

È necessario impostare la posizione ogni volta. La tua implementazione imposta solo la posizione sulla creazione della vista. Tuttavia, quando la vista viene riciclata (quando convertView non è null), la posizione non verrà impostata sul valore corretto.

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

Brillante, grazie. Non posso credere di aver passato così tanto tempo in un problema così sciocco. Ho aggiunto la mia soluzione generale come risposta separata per gli interessati. – HXCaine

0

è necessario implementare l'interfaccia OnItemClickListener, ed eliminare l'elemento nel metodo onItemClick, un parametro del metodo è la posizione.

+1

ha un pulsante, in modo che il listener non sia appropriato. Quell'ascoltatore funziona solo se l'intero elemento della lista riceve l'evento click. –

0

La mia soluzione finale era quello di utilizzare la risposta accettata da Greg e la seguente:

  • Conservare i supporti in un HashMap, con le posizioni elemento come i tasti (questo è inizializzata come vuoto nel costruttore)

    private HashMap mHolders;

  • Utilizzare questo come metodo 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(); 
} 

[Chiedo scusa per la formattazione strano. L'incorporamento del codice non funziona correttamente]