Listenansicht Scrollen Sie nach dem Aktualisieren der Liste zum Ende der Liste

292

Ich möchte sicherstellen, dass die Liste ganz nach unten gescrollt wird, nachdem ich die Listenansicht mithilfe von listAdapter aktualisiert habe, damit das zuletzt in die Liste eingegebene Element angezeigt wird. Wie kann ich das machen ?

Ich habe es versucht, aber kein Glück:

lv.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);

Vielen Dank

jramirez
quelle
Versuchen Sie dies, es funktioniert ... messagesListView.setTranscriptMode (ListView.TRANSCRIPT_MODE_NORMAL); messagesListView.setStackFromBottom (true);
Superdev
lv.setTranscriptMode (ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL) stellt nur sicher, dass listView nach dem Aufruf von adapter.notifyDataSetChanged nach unten gescrollt wird. Wenn dies nicht funktioniert, versuchen Sie, diese Eigenschaft in XML zu definieren, wie Sie in den folgenden Beiträgen sehen können.
bis

Antworten:

418

Angenommen, Sie wissen, wann sich die Listendaten geändert haben, können Sie die Liste manuell anweisen, nach unten zu scrollen, indem Sie die Listenauswahl auf die letzte Zeile setzen. Etwas wie:

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
quelle
@ Bhupendra das ist nicht nötig. Sie können auch auf Thread verzichten, wie in Wartings Antwort gezeigt.
Sagarpatidar
2
@ Bhupendra setSelection () aktualisiert die Benutzeroberfläche. Durch Aufrufen von post (Runnable) in der Ansicht stellen Sie sicher, dass der Runnable-Code auf dem Android-UI-Thread ausgeführt wird. Tun Sie dies im Allgemeinen auf diese Weise, es sei denn, Sie wissen, dass Sie sich bereits im UI-Thread befinden oder dies auf andere Weise sicherstellen.
Mason Lee
5
Es scheint auch, dass die Verwendung von Post auf einem neu eingestellten Adapter eine Bildlaufanimation verursacht, während sichergestellt wird, dass sie sich im Hauptthread befindet, und dass die Verwendung von setSelection unmittelbar nach dem Einstellen des Adapters keine Bildlaufanimation verursacht
Gianluca P.
1
@SaifHamed, wie von Mason Lee zur Antwort von Kevin kommentiert, führt dies auch dazu, dass kurze Listen oben in der Ansicht "leer" sind, anstatt unten, was höchstwahrscheinlich nicht das beabsichtigte Verhalten ist.
Dashhund
16
Sie können auch myListView.smoothScrollToPosition (myListAdapter.getCount () - 1) verwenden. für reibungsloses Scrollen
Zar E Ahmer
238

Sie müssen diese Parameter in Ihrer Listenansicht verwenden:

  • Scrollen lv.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);

  • Setzen Sie den Kopf der Liste nach unten lv.setStackFromBottom(true);

Sie können diese Parameter auch in XML einstellen, z. so was:

<ListView
   ...
   android:transcriptMode="alwaysScroll"
   android:stackFromBottom="true" />
dev.serghini
quelle
27
Beachten Sie, dass bei diesem Ansatz die Zeilen beim Hinzufügen "von unten gestapelt" werden. Dies bedeutet, dass kurze Listen oben in der Ansicht "leer" sind und nicht unten, was nicht immer gewünscht wird.
Mason Lee
2
Kurze Frage: Wie kann ich das Scrollen animieren lassen? Denn aktuell, wenn ichDataSetChanged () benachrichtige, springt es ohne Animation?!?
Georg
@Georg Haben Sie möglicherweise Animationen in den Entwickleroptionen auf Ihrem Gerät deaktiviert?
JonasCz
35

Eine Kombination aus TRANSCRIPT_MODE_ALWAYS_SCROLL und setSelection hat es für mich funktioniert

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
quelle
29

Ich habe dies als Reaktion auf einen Klick auf eine Schaltfläche erfolgreich verwendet. Ich denke, dass Sie es auch verwenden können, nachdem Sie Ihren Inhalt aktualisiert haben:

myListView.smoothScrollToPosition(theListAdapter.getCount() -1);
Alex
quelle
1
Dies ist eine großartige Lösung. Einfach, eine Zeile.
Josh Larson
12

So erhalten Sie dies in einem ListFragment:

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

Diese Antwort wurde hinzugefügt, da jemand, der eine Google-Suche nach demselben Problem mit ListFragment durchführt, diese nur findet.

Grüße

Klatschen
quelle
9

Verwenden von: Setzen Sie den Kopf der Liste nach unten lv.setStackFromBottom(true);

Hat bei mir funktioniert und die Liste wird automatisch nach unten gescrollt, wenn sie zum ersten Mal sichtbar gemacht wird. Die Liste scrollt dann wie es sollte mit TRANSCRIPT_MODE_ALWAYS_SCROLL.

Kevin Parker
quelle
6
Beachten Sie, dass bei diesem Ansatz die Zeilen beim Hinzufügen "von unten gestapelt" werden. Dies bedeutet, dass kurze Listen oben in der Ansicht "leer" und nicht unten "leer" sind.
Mason Lee
5

ich benutze

setTranscriptMode(ListView.TRANSCRIPT_MODE_NORMAL);

Um Einträge unten hinzuzufügen, und ältere Einträge scrollen oben wie ein Chat-Transkript

Plugie
quelle
Rufen Sie getListView().smoothScrollToPosition(getListAdapter.getCount() - 1);onstart auf, um zu Beginn der Aktivität nach unten zu scrollen.
Palindrom
4

Die einfachste Lösung ist:

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

Der Transkriptionsmodus ist genau das, was Sie möchten und wird von Google Talk und der SMS / MMS-Anwendung verwendet. Rufen Sie notifyDatasetChanged () auf Ihrem Adapter korrekt auf, wenn Sie Elemente hinzufügen?

Romain Guy
quelle
ja bin ich. Die Liste wird korrekt aktualisiert, beginnt jedoch immer von oben. Ich brauche es nur, um das neue Element hinzuzufügen und immer zum Ende der Liste zu scrollen.
Jramirez
Der Transkriptionsmodus wird von der SMS-App tatsächlich deaktiviert. Ich kann mich nicht genau erinnern warum.
Timmmm