Vista de lista Desplácese hasta el final de la lista después de actualizar la lista

292

Me gustaría asegurarme de que la lista se desplaza hasta el final, después de haber actualizado la vista de lista usando listAdapter, para que muestre el último elemento ingresado en la lista. Cómo puedo hacer esto ?

Intenté esto pero no tuve suerte:

lv.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);

gracias

jramirez
fuente
intente hacer esto funciona ... messagesListView.setTranscriptMode (ListView.TRANSCRIPT_MODE_NORMAL); messagesListView.setStackFromBottom (verdadero);
Superdev
lv.setTranscriptMode (ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL) solo garantiza que listView se desplazará hacia abajo después de llamar a adapter.notifyDataSetChanged. Si esto no funciona, intente definir esta propiedad en xml como puede ver en las publicaciones a continuación.
Tomm

Respuestas:

418

Suponiendo que sabe cuándo han cambiado los datos de la lista, puede indicarle manualmente que se desplace hacia abajo al establecer la selección de la lista en la última fila. Algo como:

private void scrollMyListViewToBottom() {
    myListView.post(new Runnable() {
        @Override
        public void run() {
            // Select the last row so it will scroll into view...
            myListView.setSelection(myListAdapter.getCount() - 1);
        }
    });
}
Mason Lee
fuente
@Bhupendra que no es necesario. También puedes prescindir del hilo, como se muestra en la respuesta de Warting.
sagarpatidar
2
@Bhupendra setSelection () actualiza la IU. Al llamar a post (Runnable) en la vista, se asegura de que el código Runnable se ejecute en el hilo de la interfaz de usuario de Android. En general, hágalo de esta manera a menos que sepa que ya está en el hilo de la interfaz de usuario, o que se asegura de eso por otros medios.
Mason Lee
55
también parece que el uso de la publicación en un adaptador recién configurado provoca animación de desplazamiento mientras se asegura de estar en el hilo principal y el uso de setSelection inmediatamente después de configurar el adaptador no provoca animación de desplazamiento
Gianluca P.
1
@SaifHamed, como comentó Mason Lee sobre la respuesta de Kevin, esto también hace que las listas cortas tengan un espacio "vacío" en la parte superior de la vista en lugar de la parte inferior, lo que probablemente no sea el comportamiento deseado.
dashhund
16
también puede usar myListView.smoothScrollToPosition (myListAdapter.getCount () - 1); para un desplazamiento suave
Zar E Ahmer
238

Debe usar estos parámetros en su vista de lista:

  • Desplazarse lv.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);

  • Establecer el encabezado de la lista al final lv.setStackFromBottom(true);

También puede establecer estos parámetros en XML, por ejemplo. Me gusta esto:

<ListView
   ...
   android:transcriptMode="alwaysScroll"
   android:stackFromBottom="true" />
dev.serghini
fuente
27
Tenga en cuenta que con este enfoque, las filas "se apilan desde la parte inferior" de la vista a medida que se agregan. Esto significa que las listas cortas tendrán un espacio "vacío" en la parte superior de la vista en lugar de en la parte inferior, que no siempre es lo que uno quiere.
Mason Lee
2
Pregunta rápida: ¿De alguna manera puedo hacer que el desplazamiento se anime? ¿Porque actualmente cuando notifico aDataSetChanged () salta sin animación?!?
Georg
@ Georgia ¿Ha deshabilitado las animaciones en las Opciones de desarrollador en su dispositivo?
JonasCz - Restablece a Monica
35

Una combinación de TRANSCRIPT_MODE_ALWAYS_SCROLL y setSelection me hizo funcionar

ChatAdapter adapter = new ChatAdapter(this);

ListView lv = (ListView) findViewById(R.id.chatList);
lv.setTranscriptMode(AbsListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);
lv.setAdapter(adapter);

adapter.registerDataSetObserver(new DataSetObserver() {
    @Override
    public void onChanged() {
        super.onChanged();
        lv.setSelection(adapter.getCount() - 1);    
    }
});
Wärting
fuente
29

He tenido éxito al usar esto en respuesta a un clic en el botón, así que supongo que también puedes usarlo después de actualizar tu contenido:

myListView.smoothScrollToPosition(theListAdapter.getCount() -1);
Álex
fuente
1
Esta es una gran solución. Simple, una línea.
Josh Larson
12

Para obtener esto en un ListFragment:

getListView().setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL); 
getListView().setStackFromBottom(true);`

Agregó esta respuesta porque si alguien busca en Google el mismo problema con ListFragment, simplemente encuentra esto ...

Saludos

Klatschen
fuente
9

Uso: establezca el encabezado de la lista en la parte inferior lv.setStackFromBottom(true);

Funcionó para mí y la lista se desplaza hacia abajo automáticamente cuando se hace visible por primera vez. La lista se desplaza como debería con TRANSCRIPT_MODE_ALWAYS_SCROLL.

Kevin Parker
fuente
66
Tenga en cuenta que con este enfoque, las filas "se apilan desde la parte inferior" de la vista a medida que se agregan. Esto significa que las listas cortas tendrán un espacio "vacío" en la parte superior de la vista en lugar de la parte inferior.
Mason Lee
5

yo suelo

setTranscriptMode(ListView.TRANSCRIPT_MODE_NORMAL);

para agregar entradas en la parte inferior, y las entradas más antiguas se desplazan desde la parte superior, como una transcripción de chat

Plugie
fuente
Llame getListView().smoothScrollToPosition(getListAdapter.getCount() - 1);al inicio para desplazarse hasta el final al comienzo de la actividad.
palindrom
4

La solución más simple es:

    listView.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);
    listView.setStackFromBottom(true);
ucMedia
fuente
3

El modo de transcripción es lo que desea y lo utilizan Google Talk y la aplicación de SMS / MMS. ¿Está llamando correctamente a notifyDatasetChanged () en su adaptador cuando agrega elementos?

Romain Guy
fuente
sí lo soy. la lista se actualiza correctamente, pero siempre comienza desde arriba. Solo lo necesito para agregar el nuevo elemento y siempre desplazarme al final de la lista.
jramirez
El modo de transcripción en realidad está deshabilitado por la aplicación de SMS. No puedo recordar por qué exactamente.
Timmmm el