2011-11-26 15 views
42

Estoy usando un OnScrollListener para agregar elementos dinámicamente a un ListView cuando el usuario se desplaza hacia la parte inferior. Después de agregar los datos al adaptador y llamar a notifyDataSetChanged, el ListView vuelve a la parte superior. Idealmente, me gustaría mantener el puesto en ListView. ¿Alguna idea sobre cómo debo hacer esto?Posición de retención en ListView después de llamar notifyDataSetChanged

+0

Hola puede usted por favor compartir la forma u han utilizado retener y estado actual de la vista de lista en OnScrollListener ... estoy haciendo igual, pero puedo actualizar la lista de tareas asíncrono ..... ... no funciona de alguna forma – ANUP

+3

Solución simple: http://stackoverflow.com/a/28149739/1468093 –

+0

utilice la respuesta de @KamranAhmed. solución simple y elegante. de hecho correctos, incluso –

Respuesta

96

¿Podría ser esto lo que quieres?

// save index and top position 
int index = mList.getFirstVisiblePosition(); 
View v = mList.getChildAt(0); 
int top = (v == null) ? 0 : v.getTop(); 

// notify dataset changed or re-assign adapter here 

// restore the position of listview 
mList.setSelectionFromTop(index, top); 

EDITAR 28/09/2017:

La API ha cambiado un poco desde 2015. Es similar, pero ahora sería:

// save index and top position 
int index = mList.FirstVisiblePosition; //This changed 
View v = mList.getChildAt(0); 
int top = (v == null) ? 0 : v.Top; //this changed 

// notify dataset changed or re-assign adapter here 

// restore the position of listview 
mList.setSelectionFromTop(index, top); 
+8

Gracias. Si desea agregar elementos al principio de la lista sin ver la actualización, deberá agregar la cantidad de elementos que agregó al índice int. int index = mList.getFirstVisiblePosition() + NUMBER_OF_ADDED_ITEMS; –

+5

Si setSelection no funciona inmediatamente después de llamar a notifyDataSetChanged, aquí hay una solución alternativa: getListView().postDelayed (nuevo Runnable() { @Override public void run() { getListView(). setSelection (8); } }, 500); Error de Android supuestamente asignado, por lo que esto debería solucionarse en algún momento: https://code.google.com/p/android/issues/detail?id=6741 – d2vid

+4

Funcionando perfectamente. Además, en caso de que ayude a otra persona, al principio no funcionó para mí. Hasta que me di cuenta de que en mi sabiduría infinita anterior, había agregado 'lv.setTranscriptMode (AbsListView.TRANSCRIPT_MODE_ALWAYS_SCROLL)'. No hagas eso ... se desplazará con fuerza hacia la parte inferior de tu lista hasta que hayas sacado la mayor parte de tu cabello. hah. – wired00

6

La situación:

Cuando configura un adaptador para su vista de lista, actualiza su estado. Por lo tanto, normalmente se desplaza automáticamente.

La solución:

Asignar un adaptador para Listview si no tiene ninguna, de lo contrario sólo se actualizará el conjunto de datos del adaptador asignado, no volver a ponerlo en su vista de lista.

Un tutorial detallado se explica en el siguiente enlace;

Android ListView: Maintain your scroll position when you refresh

buena suerte!

+1

Esto funciona de una manera como la posición de desplazamiento no se mueve si agrego un elemento adicional pero la lista dentro de la vista salta hacia abajo para acomodar el nuevo elemento. – Simon

+0

Esta es la solución correcta, no se requiere "piratería" para obtener algo tan simple. – Ethenyl

0

Implementé el postDelayed y estaba parpadeando al actualizar. Busqué más y descubrí que estaba haciendo las cosas mal. Básicamente, no debería crear un nuevo adaptador cada vez que quisiera cambiar los datos. Terminé haciéndolo de esta manera y funciona:

//goes into your adapter 
public void repopulateData(String[] objects) { 
    this.objects = null; 
    this.objects = objects; 
    notifyDataSetChanged(); 
} 

//goes into your activity or list 
if (adapter == null) { 
    adapter = new Adapter(); 
} else { 
    adapter.repopulateData((String[])data); 
} 

Espero que esto ayude.

0

estoy usando

listView.getFirstVisiblePosition

para mantener la última posición visible.

0

Ir con el modo de transcripción de listview.

0

probar este

 boolean first=true; 
     protected void onPostExecute(Void result) 
     { 

     if (first == true) { 
     listview.setAdapter(customAdapter); 
     first=false; 
     } 
     else 
     customAdapter.notifyDataSetChanged(); 
     } 
Cuestiones relacionadas