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


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

@ 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" />

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

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

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


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.


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


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

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?


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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.