2011-01-04 19 views
8

Estoy utilizando un BaseAdapter personalizado para mostrar elementos en un ListView. Los elementos son solo cadenas que se mantienen en una ArrayList.Eliminación de elementos de un ListView utilizando un BaseAdapter personalizado

Los elementos de la lista tienen un botón para eliminarlos (X roja grande), y me gustaría eliminar el elemento de ArrayList y notificar al ListView para que se actualice solo.

Sin embargo, cada implementación que he intentado le da números de posición misteriosos, por lo que, por ejemplo, al hacer clic en el botón eliminar del elemento 2 se eliminarán los elementos 5. Parece ser casi completamente al azar.

Una cosa a tener en cuenta es que los elementos pueden repetirse, pero deben mantenerse en el mismo orden. Por ejemplo, puedo tener "irlandés" dos veces, como elementos 3 y 7.

Mi código es el siguiente:

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

que posteriormente se intenta recuperar la posición del elemento eliminado por el acaparamiento de la etiqueta, pero siempre la posición incorrecta en la lista. No hay un patrón notable en la posición dada aquí, siempre parece aleatorio.

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

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

    ... 
    ... 
    ... 
} 

yo sería muy feliz de simplemente eliminar el elemento del ArrayList y tienen actualizar el ListView en sí, sino la posición que estoy recibiendo es incorrecta, así que no puedo hacer eso.

Tenga en cuenta que hice, al principio, tener deleteButton clickListener dentro del método getView, y usé 'position' para eliminar el valor, pero tuve el mismo problema.

Cualquier sugerencia apreciada, esto realmente me irrita.

Respuesta

5

Tiene que establecer la posición cada vez. Su implementación solo establece la posición en la creación de la vista. Sin embargo, cuando la vista se recicla (cuando convertView no es nulo), la posición no se establecerá en el valor correcto.

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, gracias. No puedo creer que haya pasado tanto tiempo en un problema tan tonto. He agregado mi solución general como una respuesta separada para los interesados. – HXCaine

0

que necesita para implementar la interfaz OnItemClickListener, y eliminar el elemento en el método onItemClick, un parámetro del método es la posición.

+1

tiene un botón, por lo que el oyente no será apropiado. Ese oyente solo funciona si todo el elemento de la lista recibe el evento click. –

0

Mi solución final era utilizar la respuesta aceptada por Greg y los siguientes:

  • tienda de los titulares en un HashMap, con las posiciones de los elementos como el teclado (esto es inicializado como vacíos en el constructor)

    private HashMap mHolders;

  • utilizar esto como el método 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(); 
} 

[Por favor, disculpe el formato extraño. El código de incrustación no funciona correctamente]

Cuestiones relacionadas