2010-06-02 23 views
36

Tengo un ListView en un ArrayAdapter personalizado que muestra un icono ImageView y un TextView en cada fila. Cuando hago la lista el tiempo suficiente para permitirle desplazarme, el orden comienza correctamente, pero cuando empiezo a desplazarme hacia abajo, algunas de las entradas anteriores comienzan a reaparecer. Si me desplazo hacia atrás, el orden anterior cambia. Hacer esto repetidamente eventualmente hace que todo el orden de la lista sea aparentemente aleatorio. Por lo tanto, si se desplaza por la lista, el orden secundario cambia o el dibujo no se actualiza correctamente.ListView en orden de ArrayAdapter get mixed cuando se desplaza

¿Qué podría causar que algo así ocurra? Necesito que el orden en que se muestran los elementos para el usuario sea del mismo orden en que se agregaron a ArrayList, o al MENOS que permanezcan en un orden estático. Si necesito proporcionar información más detallada, házmelo saber. Cualquier ayuda es apreciada. Gracias.

+1

que tienen lista muy larga para mostrar, que pasa conmigo también – Zoombie

Respuesta

3

ListView reutiliza objetos de vista cuando se desplaza. ¿Estás anulando el método getView? Debe asegurarse de configurar cada propiedad para cada vista, no suponga que recordará lo que tenía antes. Si publica ese método, es probable que alguien lo señale en la parte incorrecta.

56

Tenía problemas similares, pero al hacer clic en un elemento de la lista personalizada, los elementos de la pantalla se invertían en secuencia. Si volviera a hacer clic, retrocederían a donde estaban originalmente.

Después de leer esto, verifiqué mi código donde sobrecargo el método getView. Estaba obteniendo la vista desde la vista convertida, y si era nula, ahí es cuando construía mis cosas. Sin embargo, después de colocar un punto de interrupción, descubrí que llamaba a este método en cada clic y en los clics posteriores, convertView no era nulo, por lo tanto, los elementos no se estaban configurando.

Aquí es un ejemplo de lo que era:


public View getView(int position, View convertView, ViewGroup parent) 
{ 
    View view = convertView; 
    if (view == null) 
    { 
     LayoutInflater vi = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     view = vi.inflate(R.layout.listitemrow, null); 

     RssItem rssItem = (RssItem) super.getItem(position); 
     if (rssItem != null) 
     { 
      TextView title = (TextView) view.findViewById(R.id.rowtitle); 
      if (title != null) 
      { 
       title.setText(rssItem.getTitle()); 
      } 
     } 
    } 
    return view; 
} 

El sutil cambio se está moviendo la llave de cierre para el registro de entrada nula en la vista hasta justo después de inflar:


public View getView(int position, View convertView, ViewGroup parent) 
{ 
    View view = convertView; 
    if (view == null) 
    { 
     LayoutInflater vi = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     view = vi.inflate(R.layout.listitemrow, null); 
    } 
    RssItem rssItem = (RssItem) super.getItem(position); 
    if (rssItem != null) 
    { 
     TextView title = (TextView) view.findViewById(R.id.rowtitle); 
     if (title != null) 
     { 
      title.setText(rssItem.getTitle()); 
     } 
    } 
    return view; 
} 

espero que este ayuda a otros que experimentan este mismo problema.

+1

Esta es la respuesta correcta. Ojalá pudiera aceptarlo por ti. – Ian1971

+0

@farcrats resolvió mi problema también ... +1 para esta respuesta ... – Dinash

+0

Esto de hecho me ayudó también. Gracias por la clara explicación +1 – Sebs

4

Para aclarar aún más la respuesta de farcats a continuación en forma más general, aquí es mi explicación:

El vi.inflate funcionamiento (se necesita aquí para el análisis de la distribución de una fila a partir de XML y la creación de el objeto View apropiado) está envuelto por una declaración if (ver == nulo) para la eficiencia, por lo que el inflado del mismo objeto no ocurrirá una y otra vez cada vez que aparece en la vista.

SIN EMBARGO, las otras partes del método getView se utilizan para establecer otros parámetros y, por lo tanto, NO deben incluirse en la declaración if (ver == nulo).

Similarmente, en otra implementación común de este método, algunos elementos Textview, ImageView o ImageButton necesita ser poblada por los valores de la lista [posición], utilizando findViewById y después de que .setText o .setImageBitmap operaciones. Estas operaciones deben venir después de ambos creando una vista desde cero por inflación y obteniendo una vista existente si no es nula.

Otro buen ejemplo donde se aplica esta solución para BaseAdapter aparece en BaseAdapter causing ListView to go out of order when scrolled

0

Tengo un ListView, AdapterView y una vista (search_options) que contiene EditarTexto y 3 Spinners. Los elementos ListView son varias copias de la distribución (search_options), donde el usuario puede agregar más opciones en ListView y luego hacer clic en buscar para enviar la consulta sql creada de acuerdo con las opciones de los usuarios.

Encontré que las mixto de mezcla convertView así que agregué una lista global (myViews) en actividad y se lo pasé a ArrayAdapter. Luego, en ArrayAdapter (getView) agrego cada vista recién agregada a él (myViews).

También en getView en lugar de verificar si convertView es nulo, verifico si la lista global (myViews) tiene una vista sobre la posición seleccionada ... ¡¡resolvió totalmente los problemas después de perder 3 días leyendo internet !!

1- Actividad de añadir lo siguiente:

Map<Integer, View> myViews = new HashMap<>(); 

y luego pasarlo a ArrayAdapter utilizando el constructor del adaptador.

mSOAdapter = new SearchOptionsAdapter(getActivity(), resultStrs, myViews); 

2- en getView:

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 

    View view; 
    ViewHolder viewHolder; 

    if (!myViews.containsKey(position)) { 
     viewHolder = new ViewHolder(); 
     LayoutInflater inflater = LayoutInflater.from(getContext()); 
     view = inflater.inflate(R.layout.search_options, parent, false); 

     /// ...... YOUR CODE 

     myViews.put(position, view); 

     FontUtils.setCustomFontsIn(view, getContext().getAssets()); 

    }else { 
     view = myViews.get(position); 
    } 

    return view; 
} 

Finalmente hay elementos de mezcla más ...

Cuestiones relacionadas