Eine Lösung besteht darin, ein zu implementieren OnScrollListenerund Änderungen (wie das Hinzufügen von Elementen usw.) an dem ListAdapterin einem geeigneten Zustand in seiner onScrollMethode vorzunehmen .
Das Folgende ListActivityzeigt eine Liste von Ganzzahlen, beginnend mit 40, und fügt Elemente hinzu, wenn der Benutzer zum Ende der Liste blättert.
Sie sollten natürlich separate Threads für Aktionen mit langer Laufzeit verwenden (z. B. das Laden von Webdaten) und möglicherweise den Fortschritt des letzten Listenelements anzeigen (wie dies bei Markt- oder Google Mail-Apps der Fall ist).
Huh, würde dies nicht die Vergrößerung des Adapters auslösen, wenn Sie aufhören würden, in der Mitte des Bildschirms zu scrollen? Es sollte nur die nächsten 10 laden, wenn es tatsächlich die Liste unten erreicht.
Matthias
9
Ich bemerke viele Beispiele wie dieses mit BaseAdapter. Wenn Sie eine Datenbank verwenden, möchten Sie einen SimpleCursorAdapter verwenden. Wenn Sie der Liste hinzufügen müssen, aktualisieren Sie Ihre Datenbank, rufen Sie einen neuen Cursor ab und verwenden Sie SimpleCursorAdapter # changeCursor zusammen mit notifyDataSetChanged. Es ist keine Unterklasse erforderlich und die Leistung ist besser als bei einem BaseAdapter (wiederum nur, wenn Sie eine Datenbank verwenden).
Brack
1
Nach dem Aufruf von notifyDataSetChanged () steht es ganz oben auf der Liste. Wie kann ich dies verhindern?
Unentschieden
2
Ein Hinweis - Ich habe diesen Ansatz verwendet, musste jedoch eine Überprüfung hinzufügen, ob sichtbarer Wert 0 ist. Für jede Liste erhalte ich einen Rückruf an onScroll, wobei firstVisible, sichtbarer Betrag und totalCount alle 0 sind, was technisch die Bedingung erfüllt, dies jedoch nicht ist wenn ich mehr laden will.
Eric Mill
5
Ein weiteres Problem mit diesem Code besteht darin, dass die Bedingung firstVisible + visibleCount >= totalCountbei mehreren Aufrufen des Listeners mehrmals erfüllt wird. Wenn es sich bei der Funktion "Mehr laden" um eine Webanforderung handelt (höchstwahrscheinlich), fügen Sie eine weitere Überprüfung hinzu, ob eine Anforderung ausgeführt wird oder nicht. Überprüfen Sie andererseits, ob die Gesamtanzahl nicht der vorherigen Gesamtanzahl entspricht, da nicht mehrere Anforderungen für dieselbe Anzahl von Elementen in der Liste erforderlich sind.
Subin Sebastian
94
Ich wollte nur eine Lösung beitragen, die ich für meine App verwendet habe.
Es basiert auch auf der OnScrollListenerBenutzeroberfläche, aber ich habe festgestellt, dass es auf Low-End-Geräten eine viel bessere Bildlaufleistung aufweist, da während der Bildlaufvorgänge keine der Berechnungen für die sichtbare Anzahl / Gesamtanzahl durchgeführt werden.
Lassen Sie Ihre ListFragmentoder ListActivityimplementierenOnScrollListener
Fügen Sie dieser Klasse die folgenden Methoden hinzu:
@Overridepublicvoid onScroll(AbsListView view,int firstVisibleItem,int visibleItemCount,int totalItemCount){//leave this empty}@Overridepublicvoid onScrollStateChanged(AbsListView listView,int scrollState){if(scrollState == SCROLL_STATE_IDLE){if(listView.getLastVisiblePosition()>= listView.getCount()-1- threshold){
currentPage++;//load more list items:
loadElements(currentPage);}}}
Wo currentPagebefindet sich die Seite Ihrer Datenquelle, die Ihrer Liste hinzugefügt werden soll, und thresholddie Anzahl der Listenelemente (vom Ende an gezählt), die, falls sichtbar, den Ladevorgang auslösen sollen. Wenn Sie setzen thresholdauf 0, zum Beispiel, hat der Benutzer bis zum Ende der Liste , um scrollen , um weitere Elemente zu laden.
(optional) Wie Sie sehen, wird die "Mehrlastprüfung" nur aufgerufen, wenn der Benutzer den Bildlauf beendet. Um die Benutzerfreundlichkeit zu verbessern, können Sie über aufblasen und am Ende der Liste einen Ladeindikator hinzufügen listView.addFooterView(yourFooterView). Ein Beispiel für eine solche Fußzeilenansicht:
(optional) Entfernen Sie abschließend diese Ladeanzeige, indem Sie aufrufen, listView.removeFooterView(yourFooterView)wenn keine Elemente oder Seiten mehr vorhanden sind.
Ich habe es versucht, aber es funktioniert nicht für ListFragment. Wie kann es in ListFragment verwendet werden?
Zeeshan
Nun, ich benutze es ListFragmentauch ohne Probleme - folge einfach jedem der obigen Schritte und es wird dir gut gehen;) Oder könntest du irgendwelche Fehlermeldungen geben?
Saschoar
Was Sie möglicherweise verpasst haben, wird in dieser SO-Antwort erklärt: stackoverflow.com/a/6357957/1478093 -getListView().setOnScrollListener(this)
TBieniek
7
Hinweis: Das Hinzufügen und Entfernen der Fußzeile in der Listenansicht ist problematisch (die Fußzeile wird nicht angezeigt, wenn setAdapter vor dem Hinzufügen der Fußzeile aufgerufen wird). Am Ende habe ich die Sichtbarkeit der Fußzeilenansicht direkt geändert, ohne sie zu entfernen.
DVD
Was muss in den loadElements (currentPage) hinzugefügt werden ??? Ich meine, rufe ich meine AsyncTask oder einen Thread auf?
android_developer
20
Sie können das Ende der Liste mithilfe von onScrollListener erkennen. Der Arbeitscode wird unten dargestellt:
Eine andere Möglichkeit, dies zu tun (innerhalb des Adapters), ist wie folgt:
publicView getView(int pos,View v,ViewGroup p){if(pos==getCount()-1){
addMoreData();//should be asynctask or thread}return view;}
Beachten Sie, dass diese Methode häufig aufgerufen wird. Sie müssen daher eine weitere Bedingung hinzufügen, um mehrere Aufrufe von zu blockieren addMoreData().
Wenn Sie alle Elemente zur Liste hinzufügen, rufen Sie notifyDataSetChanged () in Ihrem Adapter auf, um die Ansicht zu aktualisieren (sie sollte auf dem UI-Thread ausgeführt werden - runOnUiThread ).
Es ist eine schlechte Praxis, andere Dinge zu tun, als eine Ansicht zurückzugeben getView. Zum Beispiel können Sie nicht garantieren, dass dies posvom Benutzer angezeigt wird. Es könnte einfach ListView-Messmaterial sein.
Thomas Ahle
Ich möchte mehr Elemente laden, nachdem 10 Elemente gescrollt wurden. Ich stelle jedoch fest, dass das Laden beginnt, bevor der 10. Artikel sichtbar ist. Dies bedeutet, dass der 9. Artikel angezeigt wird. Wie kann man dies stoppen?
Es nutzt das Volley HTTP library, was das Networking für Android-Apps einfacher und vor allem schneller macht. Volley ist über das offene AOSP-Repository verfügbar.
Der angegebene Code zeigt:
ListView, die mit HTTP-paginierten Anforderungen gefüllt ist.
Es mag etwas spät sein, aber die folgende Lösung ist in meinem Fall sehr nützlich. In gewisser Weise müssen Sie nur Ihre ListView a hinzufügen Footerund dafür erstellen addOnLayoutChangeListener.
ListView listView1 =(ListView) v.findViewById(R.id.dialogsList);// Your listViewView loadMoreView = getActivity().getLayoutInflater().inflate(R.layout.list_load_more,null);// Getting your layout of FooterView, which will always be at the bottom of your listview. E.g. you may place on it the ProgressBar or leave it empty-layout.
listView1.addFooterView(loadMoreView);// Adding your View to your listview ...
loadMoreView.addOnLayoutChangeListener(newView.OnLayoutChangeListener(){@Overridepublicvoid onLayoutChange(View v,int left,int top,int right,int bottom,int oldLeft,int oldTop,int oldRight,int oldBottom){Log.d("Hey!","Your list has reached bottom");}});
Dieses Ereignis wird einmal ausgelöst, wenn eine Fußzeile sichtbar wird und wie ein Zauber wirkt.
Der Schlüssel zu diesem Problem besteht darin, das Ereignis "Mehr laden" zu erkennen, eine asynchrone Anforderung für Daten zu starten und dann die Liste zu aktualisieren. Außerdem wird ein Adapter mit Ladeanzeige und anderen Dekorateuren benötigt. Tatsächlich ist das Problem in einigen Eckfällen sehr kompliziert. Nur eine OnScrollListenerImplementierung reicht nicht aus, da die Elemente manchmal den Bildschirm nicht ausfüllen.
Ich habe ein persönliches Paket geschrieben, das endlose Listen RecyclerViewunterstützt und außerdem eine asynchrone Loader-Implementierung bereitstellt, mit AutoPagerFragmentder es sehr einfach ist, Daten aus einer mehrseitigen Quelle abzurufen. Es kann jede gewünschte Seite in ein RecyclerViewbenutzerdefiniertes Ereignis laden , nicht nur die nächste Seite.
Ich habe in einer anderen Lösung gearbeitet, die dieser sehr ähnlich ist, aber ich verwende a footerView, um dem Benutzer die Möglichkeit zu geben, mehr Elemente herunterzuladen, indem footerViewich auf klicke . Ich verwende ein "Menü", das über ListViewund unter dem angezeigt wird In der übergeordneten Ansicht verbirgt dieses "Menü" den unteren Rand des Menüs. ListViewWenn listViewalso das Menü gescrollt wird und der Bildlaufstatus inaktiv ist, wird das Menü erneut angezeigt. Wenn der Benutzer jedoch zum Ende des Menüs blättert listView, "frage" ich nach Wenn footerViewin diesem Fall das angezeigt wird, wird das Menü nicht angezeigt und der Benutzer kann sehen footerView, dass weitere Inhalte geladen werden. Hier der Code:
Ich weiß, es ist eine alte Frage und die Android-Welt ist größtenteils zu RecyclerViews übergegangen, aber für alle Interessierten mag diese Bibliothek sehr interessant sein.
Es verwendet den BaseAdapter, der mit der ListView verwendet wird, um zu erkennen, wann die Liste zum letzten Element gescrollt wurde oder wann vom letzten Element weg gescrollt wird.
Es wird mit einem Beispielprojekt (kaum 100 Zeilen Aktivitätscode) geliefert, mit dem Sie schnell verstehen können, wie es funktioniert.
Beachten Sie, wie die getView-Methode des BoysAdapter einen Aufruf der Methode der Superklasse EndlessAdapter zurückgibt getView. Dies ist zu 100% wichtig.
Um den Adapter zu erstellen, gehen Sie wie folgt vor:
Das loadMoreElement ist eine Schaltfläche oder ein anderes UI-Element, auf das geklickt werden kann, um weitere Daten aus der URL abzurufen. Wenn der Adapter wie im Code beschrieben platziert wird, weiß er genau, wann diese Schaltfläche angezeigt und wann sie deaktiviert werden muss. Erstellen Sie einfach die Schaltfläche in Ihrer XML-Datei und platzieren Sie sie wie im obigen Adaptercode gezeigt.
Antworten:
Eine Lösung besteht darin, ein zu implementieren
OnScrollListener
und Änderungen (wie das Hinzufügen von Elementen usw.) an demListAdapter
in einem geeigneten Zustand in seineronScroll
Methode vorzunehmen .Das Folgende
ListActivity
zeigt eine Liste von Ganzzahlen, beginnend mit 40, und fügt Elemente hinzu, wenn der Benutzer zum Ende der Liste blättert.Sie sollten natürlich separate Threads für Aktionen mit langer Laufzeit verwenden (z. B. das Laden von Webdaten) und möglicherweise den Fortschritt des letzten Listenelements anzeigen (wie dies bei Markt- oder Google Mail-Apps der Fall ist).
quelle
firstVisible + visibleCount >= totalCount
bei mehreren Aufrufen des Listeners mehrmals erfüllt wird. Wenn es sich bei der Funktion "Mehr laden" um eine Webanforderung handelt (höchstwahrscheinlich), fügen Sie eine weitere Überprüfung hinzu, ob eine Anforderung ausgeführt wird oder nicht. Überprüfen Sie andererseits, ob die Gesamtanzahl nicht der vorherigen Gesamtanzahl entspricht, da nicht mehrere Anforderungen für dieselbe Anzahl von Elementen in der Liste erforderlich sind.Ich wollte nur eine Lösung beitragen, die ich für meine App verwendet habe.
Es basiert auch auf der
OnScrollListener
Benutzeroberfläche, aber ich habe festgestellt, dass es auf Low-End-Geräten eine viel bessere Bildlaufleistung aufweist, da während der Bildlaufvorgänge keine der Berechnungen für die sichtbare Anzahl / Gesamtanzahl durchgeführt werden.ListFragment
oderListActivity
implementierenOnScrollListener
Fügen Sie dieser Klasse die folgenden Methoden hinzu:
Wo
currentPage
befindet sich die Seite Ihrer Datenquelle, die Ihrer Liste hinzugefügt werden soll, undthreshold
die Anzahl der Listenelemente (vom Ende an gezählt), die, falls sichtbar, den Ladevorgang auslösen sollen. Wenn Sie setzenthreshold
auf0
, zum Beispiel, hat der Benutzer bis zum Ende der Liste , um scrollen , um weitere Elemente zu laden.(optional) Wie Sie sehen, wird die "Mehrlastprüfung" nur aufgerufen, wenn der Benutzer den Bildlauf beendet. Um die Benutzerfreundlichkeit zu verbessern, können Sie über aufblasen und am Ende der Liste einen Ladeindikator hinzufügen
listView.addFooterView(yourFooterView)
. Ein Beispiel für eine solche Fußzeilenansicht:(optional) Entfernen Sie abschließend diese Ladeanzeige, indem Sie aufrufen,
listView.removeFooterView(yourFooterView)
wenn keine Elemente oder Seiten mehr vorhanden sind.quelle
ListFragment
auch ohne Probleme - folge einfach jedem der obigen Schritte und es wird dir gut gehen;) Oder könntest du irgendwelche Fehlermeldungen geben?getListView().setOnScrollListener(this)
Sie können das Ende der Liste mithilfe von onScrollListener erkennen. Der Arbeitscode wird unten dargestellt:
Eine andere Möglichkeit, dies zu tun (innerhalb des Adapters), ist wie folgt:
Beachten Sie, dass diese Methode häufig aufgerufen wird. Sie müssen daher eine weitere Bedingung hinzufügen, um mehrere Aufrufe von zu blockieren
addMoreData()
.Wenn Sie alle Elemente zur Liste hinzufügen, rufen Sie notifyDataSetChanged () in Ihrem Adapter auf, um die Ansicht zu aktualisieren (sie sollte auf dem UI-Thread ausgeführt werden - runOnUiThread ).
quelle
getView
. Zum Beispiel können Sie nicht garantieren, dass diespos
vom Benutzer angezeigt wird. Es könnte einfach ListView-Messmaterial sein.Bei
Ognyan Bankov GitHub
fand ich eine einfache und funktionierende Lösung!Es nutzt das
Volley HTTP library
, was das Networking für Android-Apps einfacher und vor allem schneller macht. Volley ist über das offene AOSP-Repository verfügbar.Der angegebene Code zeigt:
Für die zukünftige Konsistenz gabelte ich Bankovs Repo .
quelle
Hier ist eine Lösung, die es auch einfach macht, eine Ladeansicht am Ende der ListView anzuzeigen, während sie geladen wird.
Sie können die Klassen hier sehen:
https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/helper/ListViewWithLoadingIndicatorHelper.java - Hilfsprogramm zur Verwendung des Funktionen ohne Erweiterung von SimpleListViewWithLoadingIndicator.
https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/listener/EndlessScrollListener.java - Listener, der Daten lädt, wenn der Benutzer ist im Begriff, den unteren Rand der ListView zu erreichen.
https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/view/SimpleListViewWithLoadingIndicator.java - The EndlessListView. Sie können diese Klasse direkt verwenden oder erweitern.
quelle
Es mag etwas spät sein, aber die folgende Lösung ist in meinem Fall sehr nützlich. In gewisser Weise müssen Sie nur Ihre ListView a hinzufügen
Footer
und dafür erstellenaddOnLayoutChangeListener
.http://developer.android.com/reference/android/widget/ListView.html#addFooterView(android.view.View)
Beispielsweise:
Dieses Ereignis wird einmal ausgelöst, wenn eine Fußzeile sichtbar wird und wie ein Zauber wirkt.
quelle
Der Schlüssel zu diesem Problem besteht darin, das Ereignis "Mehr laden" zu erkennen, eine asynchrone Anforderung für Daten zu starten und dann die Liste zu aktualisieren. Außerdem wird ein Adapter mit Ladeanzeige und anderen Dekorateuren benötigt. Tatsächlich ist das Problem in einigen Eckfällen sehr kompliziert. Nur eine
OnScrollListener
Implementierung reicht nicht aus, da die Elemente manchmal den Bildschirm nicht ausfüllen.Ich habe ein persönliches Paket geschrieben, das endlose Listen
RecyclerView
unterstützt und außerdem eine asynchrone Loader-Implementierung bereitstellt, mitAutoPagerFragment
der es sehr einfach ist, Daten aus einer mehrseitigen Quelle abzurufen. Es kann jede gewünschte Seite in einRecyclerView
benutzerdefiniertes Ereignis laden , nicht nur die nächste Seite.Hier ist die Adresse: https://github.com/SphiaTower/AutoPagerRecyclerManager
quelle
Die beste Lösung, die ich bisher gesehen habe, ist die FastAdapter- Bibliothek für Recycler-Ansichten. Es hat eine
EndlessRecyclerOnScrollListener
.Hier ist ein Beispiel für die Verwendung: EndlessScrollListActivity
Als ich es für endlose Bildlauflisten verwendet habe, habe ich festgestellt, dass das Setup sehr robust ist. Ich würde es auf jeden Fall empfehlen.
quelle
Ich habe in einer anderen Lösung gearbeitet, die dieser sehr ähnlich ist, aber ich verwende a
footerView
, um dem Benutzer die Möglichkeit zu geben, mehr Elemente herunterzuladen, indemfooterView
ich auf klicke . Ich verwende ein "Menü", das überListView
und unter dem angezeigt wird In der übergeordneten Ansicht verbirgt dieses "Menü" den unteren Rand des Menüs.ListView
WennlistView
also das Menü gescrollt wird und der Bildlaufstatus inaktiv ist, wird das Menü erneut angezeigt. Wenn der Benutzer jedoch zum Ende des Menüs blättertlistView
, "frage" ich nach WennfooterView
in diesem Fall das angezeigt wird, wird das Menü nicht angezeigt und der Benutzer kann sehenfooterView
, dass weitere Inhalte geladen werden. Hier der Code:Grüße.
quelle
Ich weiß, es ist eine alte Frage und die Android-Welt ist größtenteils zu RecyclerViews übergegangen, aber für alle Interessierten mag diese Bibliothek sehr interessant sein.
Es verwendet den BaseAdapter, der mit der ListView verwendet wird, um zu erkennen, wann die Liste zum letzten Element gescrollt wurde oder wann vom letzten Element weg gescrollt wird.
Es wird mit einem Beispielprojekt (kaum 100 Zeilen Aktivitätscode) geliefert, mit dem Sie schnell verstehen können, wie es funktioniert.
Einfache Verwendung:
Ein Adapter zum Halten von Boy-Objekten würde folgendermaßen aussehen:
Beachten Sie, wie die getView-Methode des BoysAdapter einen Aufruf der Methode der Superklasse EndlessAdapter zurückgibt
getView
. Dies ist zu 100% wichtig.Um den Adapter zu erstellen, gehen Sie wie folgt vor:
Das
loadMore
Element ist eine Schaltfläche oder ein anderes UI-Element, auf das geklickt werden kann, um weitere Daten aus der URL abzurufen. Wenn der Adapter wie im Code beschrieben platziert wird, weiß er genau, wann diese Schaltfläche angezeigt und wann sie deaktiviert werden muss. Erstellen Sie einfach die Schaltfläche in Ihrer XML-Datei und platzieren Sie sie wie im obigen Adaptercode gezeigt.Genießen.
quelle