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


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

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

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

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

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


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.


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


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

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?


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,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.