Widok listy Przewiń do końca listy po zaktualizowaniu listy

292

Chciałbym się upewnić, że lista jest przewijana do samego końca, po zaktualizowaniu widoku listy za pomocą listAdapter, tak aby wyświetlał ostatni element wpisany na listę. W jaki sposób mogę to zrobić ?

Próbowałem tego, ale bez powodzenia:

lv.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);

Dziękuję Ci

jramirez
źródło
spróbuj to zrobić, to działa ... messagesListView.setTranscriptMode (ListView.TRANSCRIPT_MODE_NORMAL); messagesListView.setStackFromBottom (true);
Superdev
lv.setTranscriptMode (ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL) zapewnia tylko, że listView zostanie przewinięty w dół po wywołaniu adapter.notifyDataSetChanged. Jeśli to nie działa, spróbuj zdefiniować tę właściwość w xml, jak widać w poniższych postach.
tomm

Odpowiedzi:

418

Zakładając, że wiesz, kiedy dane listy uległy zmianie, możesz ręcznie nakazać przewijanie listy w dół, ustawiając wybór listy na ostatni wiersz. Coś jak:

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
źródło
@Bhupendra, które nie są konieczne. Możesz też obejść się bez wątku, jak pokazano w odpowiedzi Wartinga.
sagarpatidar
2
@Bhupendra setSelection () aktualizuje interfejs użytkownika. Dzwoniąc do posta (Runnable) w widoku, upewniasz się, że kod Runnable jest uruchamiany w wątku interfejsu użytkownika Androida. Zasadniczo rób to w ten sposób, chyba że wiesz, że jesteś już w wątku interfejsu użytkownika, lub że zapewniasz to w inny sposób.
Mason Lee,
5
wydaje się również, że użycie posta na nowo ustawionym adapterze powoduje animację przewijania, przy jednoczesnym zapewnieniu, że znajduje się w głównym wątku, a użycie setSelection natychmiast po ustawieniu adaptera nie powoduje animacji przewijania
Gianluca P.
1
@SaifHamed, jak skomentował Mason Lee w odpowiedzi Kevina, powoduje to, że krótkie listy mają „puste” miejsce u góry widoku zamiast u dołu, co najprawdopodobniej nie jest zamierzonym zachowaniem.
Dashhund
16
możesz także użyć myListView.smoothScrollToPosition (myListAdapter.getCount () - 1); do płynnego przewijania
Zar E Ahmer
238

Musisz użyć tych parametrów w widoku listy:

  • Zwój lv.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);

  • Ustaw nagłówek listy na dole lv.setStackFromBottom(true);

Możesz również ustawić te parametry w XML, np. lubię to:

<ListView
   ...
   android:transcriptMode="alwaysScroll"
   android:stackFromBottom="true" />
dev.serghini
źródło
27
Zauważ, że przy takim podejściu wiersze „układają się od dołu” widoku podczas dodawania. Oznacza to, że krótkie listy będą miały „puste” miejsce u góry widoku zamiast u dołu, co nie zawsze jest tym, czego się chce.
Mason Lee,
2
Szybkie pytanie: Jak mogę animować przewijanie? Ponieważ obecnie, gdy I powiadomięDataSetChanged (), przeskakuje bez animacji?!?
Georg,
@Georg Czy może wyłączyłeś animacje w Opcjach programisty na swoim urządzeniu?
JonasCz - Przywróć Monikę
35

Połączenie TRANSCRIPT_MODE_ALWAYS_SCROLL i setSelection sprawiło, że zadziałało dla mnie

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
źródło
29

Udało mi się to wykorzystać w odpowiedzi na kliknięcie przycisku, więc sądzę, że możesz użyć go również po zaktualizowaniu zawartości:

myListView.smoothScrollToPosition(theListAdapter.getCount() -1);
Álex
źródło
1
To świetne rozwiązanie. Prosta, jedna linia.
Josh Larson,
12

Aby uzyskać to w ListFragment:

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

Dodano tę odpowiedź, ponieważ jeśli ktoś wyszukuje w Google ten sam problem z ListFragment, po prostu go znajduje.

pozdrowienia

Klatschen
źródło
9

Za pomocą: Ustaw nagłówek listy na dole lv.setStackFromBottom(true);

Pracowało dla mnie, a lista jest automatycznie przewijana w dół, gdy jest po raz pierwszy widoczna. Następnie lista przewija się tak, jak powinna TRANSCRIPT_MODE_ALWAYS_SCROLL.

Kevin Parker
źródło
6
Zauważ, że przy takim podejściu wiersze „układają się od dołu” widoku podczas dodawania. Oznacza to, że krótkie listy będą miały „puste” miejsce u góry widoku zamiast u dołu.
Mason Lee,
5

używam

setTranscriptMode(ListView.TRANSCRIPT_MODE_NORMAL);

aby dodać wpisy na dole, a starsze wpisy przewiń od góry, jak zapis rozmowy na czacie

Wtyczka
źródło
Wezwij program getListView().smoothScrollToPosition(getListAdapter.getCount() - 1);onstart, aby przewinąć na dół na początku działania.
palindrom
4

Najprostszym rozwiązaniem jest:

    listView.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);
    listView.setStackFromBottom(true);
ucMedia
źródło
3

Tryb transkrypcji jest tym, czego chcesz i jest używany przez Google Talk i aplikację SMS / MMS. Czy podczas dodawania elementów poprawnie wywołujesz funkcję noticeDatasetChanged () na adapterze?

Romain Guy
źródło
tak, jestem. lista poprawnie się aktualizuje, ale zawsze zaczyna się od góry. Potrzebuję go tylko, aby dodać nowy element i zawsze przewijać do końca listy.
jramirez
Tryb transkrypcji jest faktycznie wyłączony przez aplikację SMS. Nie pamiętam dlaczego dokładnie.
Timmmm,