Czy mogę dowiedzieć się, czy mój ListView jest przewijany do dołu? Rozumiem przez to, że ostatnia pozycja jest w pełni widoczna.
105
Edytowano :
Ponieważ badam ten konkretny temat w jednej z moich aplikacji, mogę napisać rozszerzoną odpowiedź dla przyszłych czytelników na to pytanie.
Zaimplementuj OnScrollListener
, ustaw własne ListView
, onScrollListener
a wtedy powinieneś być w stanie poprawnie obsługiwać rzeczy.
Na przykład:
private int preLast;
// Initialization stuff.
yourListView.setOnScrollListener(this);
// ... ... ...
@Override
public void onScroll(AbsListView lw, final int firstVisibleItem,
final int visibleItemCount, final int totalItemCount)
{
switch(lw.getId())
{
case R.id.your_list_id:
// Make your calculation stuff here. You have all your
// needed info from the parameters of this function.
// Sample calculation to determine if the last
// item is fully visible.
final int lastItem = firstVisibleItem + visibleItemCount;
if(lastItem == totalItemCount)
{
if(preLast!=lastItem)
{
//to avoid multiple calls for last item
Log.d("Last", "Last");
preLast = lastItem;
}
}
}
}
listview
jeststackFromBottom
? Próbowałem,if (0 == firstVisibleItem){//listviewtop}
ale jest to wielokrotnie wywoływane.Późna odpowiedź, ale jeśli chcesz po prostu sprawdzić, czy Twój ListView jest przewijany do końca, czy nie, bez tworzenia detektora zdarzeń, możesz użyć tej instrukcji if:
Najpierw sprawdza, czy widoczna jest ostatnia możliwa pozycja. Następnie sprawdza, czy dół ostatniego przycisku jest wyrównany z dołem ListView. Możesz zrobić coś podobnego, aby dowiedzieć się, czy jest na górze:
źródło
getChildCount()
zwraca widoki w grupie widoków, co w przypadku recyklingu widoków nie jest tym samym, co liczba elementów w adapterze. Jednak ponieważ ListView wywodzi się z AdapterView, można go używaćgetCount()
bezpośrednio w ListView.Sposób, w jaki to zrobiłem:
źródło
Coś w efekcie:
źródło
To zadziałało dla mnie.
źródło
To może być
źródło
Dość bolesne było radzenie sobie z przewijaniem, wykrywaniem, kiedy jest zakończone i rzeczywiście znajduje się na dole listy (nie na dole widocznego ekranu) i uruchamia moją usługę tylko raz, aby pobrać dane z sieci. Jednak teraz działa dobrze. Kod jest następujący, z korzyścią dla każdego, kto znajduje się w takiej samej sytuacji.
UWAGA: Musiałem przenieść mój kod związany z adapterem do onViewCreated zamiast onCreate i wykryć przewijanie głównie w ten sposób:
Tutaj RideListSimpleCursorAdapter.REACHED_THE_END jest dodatkową zmienną w moim SimpleCustomAdapter, która jest ustawiona w następujący sposób:
Dopiero spełnienie obu tych warunków oznacza, że rzeczywiście jestem na dole listy, a moja usługa będzie działać tylko raz. Jeśli nie złapię REACHED_THE_END, nawet przewijanie do tyłu uruchamia usługę ponownie, o ile ostatni element jest widoczny.
źródło
canScrollVertically(int direction)
działa dla wszystkich widoków i wydaje się robić to, o co prosiłeś, z mniejszą ilością kodu niż większość innych odpowiedzi. Wpisz liczbę dodatnią, a jeśli wynik jest fałszywy, jesteś na dole.to znaczy:
if (!yourView.canScrollVertically(1)) { //you've reached bottom }
źródło
Aby rozwinąć nieco jedną z powyższych odpowiedzi, oto, co musiałem zrobić, aby całkowicie działała. Wygląda na to, że istnieje około 6dp wbudowanego dopełnienia wewnątrz ListViews, a onScroll () był wywoływany, gdy lista była pusta. To obsługuje obie te rzeczy. Prawdopodobnie mógłby być nieco zoptymalizowany, ale jest napisany bardziej dla przejrzystości.
Uwaga dodatkowa: próbowałem kilku różnych technik konwersji z dp na piksel, a ta dp2px () była najlepsza.
źródło
Nie mogę jeszcze komentować, ponieważ nie mam wystarczającej reputacji, ale w odpowiedzi @Ali Imran i @Wroclai wydaje mi się, że czegoś brakuje. Z tym fragmentem kodu, po zaktualizowaniu preLast, nigdy więcej nie uruchomi dziennika. W moim konkretnym problemie chcę wykonać jakąś operację za każdym razem, gdy przewijam do dołu, ale po zaktualizowaniu preLast do LastItem operacja ta nigdy nie jest wykonywana ponownie.
}
Dzięki temu „else” możesz teraz wykonać swój kod (w tym przypadku Log) za każdym razem, gdy ponownie przewiniesz w dół.
źródło
źródło
Aby Twoja lista zadzwoniła, gdy lista osiągnie ostatnią pozycję i jeśli wystąpi błąd, nie spowoduje to ponownego wywołania endoflistview . Ten kod pomoże również w tym scenariuszu.
gdzie LIST_UP_THRESHOLD_VALUE może być dowolną wartością całkowitą (użyłem 5), gdzie twoja lista jest przewijana w górę i podczas powrotu do końca, spowoduje to ponowne wywołanie końca widoku listy.
źródło
Znalazłem bardzo fajny sposób na automatyczne ładowanie kolejnej strony w sposób, który nie wymaga twojej własnej
ScrollView
(jak wymaga zaakceptowana odpowiedź).W ParseQueryAdapter jest wywoływana metoda,
getNextPageView
która umożliwia dostarczenie własnego widoku niestandardowego, który pojawia się na końcu listy, gdy jest więcej danych do załadowania, więc zostanie wyzwolony dopiero po osiągnięciu końca bieżącego zestawu stron (jest to domyślnie widok „wczytaj więcej…”). Ta metoda jest wywoływana tylko wtedy, gdy jest więcej danych do załadowania, więc jest to świetne miejsce do wywołania WloadNextPage();
ten sposób adapter wykona całą ciężką pracę za Ciebie przy określaniu, kiedy należy załadować nowe dane i nie zostanie on w ogóle wywołany, jeśli masz osiągnął koniec zbioru danych.Następnie w ramach swojej aktywności / fragmentu wystarczy ustawić adapter, a nowe dane zostaną automatycznie zaktualizowane, jak magia.
źródło
Aby wykryć, czy ostatni element jest w pełni widoczny , możesz w prosty sposób dodać obliczenia na dole ostatniego widocznego elementu widoku
lastItem.getBottom()
.źródło
Poszedłem z:
źródło
W metodzie
getView()
(BaseAdapter
klasy pochodnej) można sprawdzić, czy pozycja bieżącego widoku jest równa liście elementów w plikuAdapter
. Jeśli tak jest, oznacza to, że dotarliśmy do końca / dołu listy:źródło
Znajduję lepszy sposób na wykrycie przewijania widoku listy na dole, najpierw wykryj koniec przewijania przez to
implementację onScrollListener, aby wykryć koniec przewijania w ListView
w końcu połącz odpowiedź Martijna
źródło
Wielkie dzięki za plakaty w stackoverflow! Połączyłem kilka pomysłów i stworzyłem odbiornik klas dla działań i fragmentów (więc ten kod jest bardziej wielokrotnego użytku, dzięki czemu kod jest szybszy do pisania i znacznie czystszy).
Po otrzymaniu mojej klasy wystarczy zaimplementować interfejs (i oczywiście stworzyć dla niego metodę), który jest zadeklarowany w mojej klasie i stworzyć obiekt tej klasy przekazujący argumenty.
źródło
Musisz dodać pusty zasób stopki XML do swojej listView i sprawdzić, czy ta stopka jest widoczna.
Następnie robisz to w swoim listener przewijanym listView
źródło
Jeśli ustawisz znacznik w widoku ostatniego elementu widoku listy, możesz później pobrać widok ze znacznikiem, jeśli widok jest pusty, to dlatego, że widok nie jest już ładowany. Lubię to:
jeśli chcesz wiedzieć, czy ostatni element jest załadowany
źródło
Janwilx72 ma rację, ale min sdk to 21, więc tworzę tę metodę :
dla ScrollOrientation:
Może późno, tylko dla spóźnialskich。
źródło
Jeśli używasz niestandardowego adaptera z widokiem listy (większość ludzi tak robi!), Znajdziesz tutaj piękne rozwiązanie!
https://stackoverflow.com/a/55350409/1845404
Metoda getView adaptera wykrywa, kiedy lista została przewinięta do ostatniej pozycji. Dodaje również korektę w rzadkich przypadkach, gdy wywoływana jest wcześniejsza pozycja, nawet po wyrenderowaniu przez adapter ostatniego widoku.
źródło
Zrobiłem to i działa dla mnie:
źródło
Spowoduje to przewinięcie listy do ostatniego wpisu.
źródło