Wie kann ich eine Liste erstellen, bei der ich benachrichtigt werde, wenn Sie das Ende der Liste erreichen, damit ich weitere Artikel laden kann?
Android Endlosliste
Isaak Waller
Josef Pfleger
Eine Lösung besteht darin, eine zu implementieren OnScrollListener
und nehmen Sie Änderungen (z. B. Hinzufügen von Elementen usw.) an der vor ListAdapter
in einem bequemen Zustand in seiner onScroll
Methode.
Die folgende ListActivity
zeigt eine Liste von Ganzzahlen, beginnend mit 40, und fügt Elemente hinzu, wenn der Benutzer zum Ende der Liste scrollt.
public class Test extends ListActivity implements OnScrollListener {
Aleph0 adapter = new Aleph0();
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setListAdapter(adapter);
getListView().setOnScrollListener(this);
}
public void onScroll(AbsListView view,
int firstVisible, int visibleCount, int totalCount) {
boolean loadMore = /* maybe add a padding */
firstVisible + visibleCount >= totalCount;
if(loadMore) {
adapter.count += visibleCount; // or any other amount
adapter.notifyDataSetChanged();
}
}
public void onScrollStateChanged(AbsListView v, int s) { }
class Aleph0 extends BaseAdapter {
int count = 40; /* starting amount */
public int getCount() { return count; }
public Object getItem(int pos) { return pos; }
public long getItemId(int pos) { return pos; }
public View getView(int pos, View v, ViewGroup p) {
TextView view = new TextView(Test.this);
view.setText("entry " + pos);
return view;
}
}
}
Sie sollten natürlich separate Threads für lang andauernde Aktionen (wie das Laden von Webdaten) verwenden und den Fortschritt möglicherweise im letzten Listenelement anzeigen (wie es die Market- oder Gmail-Apps tun).
-
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 die nächsten 10 nur laden, wenn es tatsächlich das Ende der Liste erreicht.
– Mathias
5. August 2010 um 10:13 Uhr
-
Ich bemerke viele Beispiele wie dieses mit BaseAdapter. Wollte erwähnen, dass Sie bei Verwendung einer Datenbank versuchen, einen SimpleCursorAdapter zu verwenden. Wenn Sie etwas zur Liste hinzufügen müssen, aktualisieren Sie Ihre Datenbank, erhalten Sie einen neuen Cursor und verwenden Sie SimpleCursorAdapter#changeCursor zusammen mit notificationDataSetChanged. Es sind keine Unterklassen erforderlich, und es funktioniert besser als ein BaseAdapter (wiederum nur, wenn Sie eine Datenbank verwenden).
– Klammer
20. Oktober 2010 um 18:51 Uhr
-
Nach dem Aufruf von notificationDataSetChanged() wird es ganz oben auf der Liste stehen, wie kann ich das verhindern?
– zeichnen
2. September 2011 um 12:57 Uhr
-
Ein Hinweis: Ich habe diesen Ansatz verwendet, musste aber eine Überprüfung hinzufügen, ob der sichtbare Zählwert 0 ist. Für jede Liste erhalte ich einen Rückruf an onScroll, wobei firstVisible, visibleCount und totalCount alle 0 sind, was technisch gesehen die Bedingung erfüllt, aber nicht ist wenn ich mehr laden möchte.
– Eric Mill
5. Januar 2012 um 22:37 Uhr
-
Ein weiteres Problem mit diesem Code ist, dass die Bedingung
firstVisible + visibleCount >= totalCount
wird mehrfach mit mehreren Aufrufen an den Hörer erfüllt. Wenn es sich bei der Load-More-Funktion um eine Webanfrage handelt (was höchstwahrscheinlich der Fall sein wird), fügen Sie eine weitere Überprüfung hinzu, ob eine Anfrage läuft oder nicht. Überprüfen Sie andererseits, ob totalCount nicht gleich der vorherigen Gesamtanzahl ist, da wir nicht mehrere Anfragen für die gleiche Anzahl von Elementen in der Liste benötigen.– C–
24. August 2012 um 20:14 Uhr
Saschoar
Ich wollte nur eine Lösung beisteuern, die ich für meine App verwendet habe.
Es basiert auch auf der OnScrollListener
Schnittstelle, aber ich fand, dass es eine viel bessere Scrollleistung auf Low-End-Geräten hat, da keine der Berechnungen der sichtbaren/Gesamtzahl während der Scrollvorgänge durchgeführt werden.
- Lass dein
ListFragment
oderListActivity
implementierenOnScrollListener
-
Fügen Sie dieser Klasse die folgenden Methoden hinzu:
@Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { //leave this empty } @Override public void 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
currentPage
ist die Seite Ihrer Datenquelle, die zu Ihrer Liste hinzugefügt werden soll, undthreshold
ist die Anzahl der Listeneinträge (vom Ende gezählt), die, falls sichtbar, den Ladevorgang auslösen sollen. Wenn Sie einstellenthreshold
zu0
muss der Benutzer beispielsweise bis zum Ende der Liste scrollen, um weitere Elemente zu laden. -
(Optional) Wie Sie sehen können, wird der “Load-More-Check” nur aufgerufen, wenn der Benutzer aufhört zu scrollen. Um die Benutzerfreundlichkeit zu verbessern, können Sie am Ende der Liste über eine Ladeanzeige aufblasen und hinzufügen
listView.addFooterView(yourFooterView)
. Ein Beispiel für eine solche Fußzeilenansicht:<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/footer_layout" android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding="10dp" > <ProgressBar android:id="@+id/progressBar1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_gravity="center_vertical" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_toRightOf="@+id/progressBar1" android:padding="5dp" android:text="@string/loading_text" /> </RelativeLayout>
-
(Optional) Entfernen Sie schließlich diesen Ladeindikator, indem Sie aufrufen
listView.removeFooterView(yourFooterView)
wenn keine Elemente oder Seiten mehr vorhanden sind.
-
Ich habe das versucht, aber es funktioniert nicht für ListFragment. Wie kann es in ListFragment verwendet werden.
– Zeeshan
13. Juli 2013 um 15:35 Uhr
-
Nun, ich benutze es mit
ListFragment
auch ohne Probleme – befolgen Sie einfach jeden der obigen Schritte und alles wird gut 😉 Oder könnten Sie irgendwelche Fehlermeldungen bereitstellen?– saschoar
14. Juli 2013 um 21:44 Uhr
-
Was Sie vielleicht übersehen haben, wird in dieser SO-Antwort erklärt: stackoverflow.com/a/6357957/1478093 –
getListView().setOnScrollListener(this)
– TBieniek
24. Juli 2013 um 9:29 Uhr
-
Hinweis: Das Hinzufügen und Entfernen von Fußzeilen in der Listenansicht ist problematisch (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
20. Oktober 2013 um 22:53 Uhr
-
Was muss in den loadElements(currentPage) hinzugefügt werden??? Ich meine, rufe ich meine AsyncTask oder einen Thread auf?
– Android-Entwickler
28. November 2013 um 8:19 Uhr
Dariusz Bacinski
Sie können das Ende der Liste mit Hilfe von erkennen onScrollListenerArbeitscode ist unten dargestellt:
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (view.getAdapter() != null && ((firstVisibleItem + visibleItemCount) >= totalItemCount) && totalItemCount != mPrevTotalItemCount) {
Log.v(TAG, "onListEnd, extending list");
mPrevTotalItemCount = totalItemCount;
mAdapter.addMoreData();
}
}
Eine andere Möglichkeit, dies zu tun (innerhalb des Adapters), ist wie folgt:
public View getView(int pos, View v, ViewGroup p) {
if(pos==getCount()-1){
addMoreData(); //should be asynctask or thread
}
return view;
}
Beachten Sie, dass diese Methode viele Male aufgerufen wird, daher müssen Sie eine weitere Bedingung hinzufügen, um mehrere Aufrufe zu blockieren addMoreData()
.
Wenn Sie alle Elemente in die Liste aufgenommen haben, rufen Sie bitte an benachrichtigenDataSetChanged() in Ihrem Adapter, um die Ansicht zu aktualisieren (es sollte im UI-Thread ausgeführt werden – runOnUiThread)
-
Es ist eine schlechte Angewohnheit, andere Dinge zu tun, als eine Ansicht zurückzugeben
getView
. Das ist Ihnen zum Beispiel nicht garantiertpos
wird vom Benutzer angezeigt. Es könnte einfach ListView sein, das Zeug misst.– Thomas Ahle
13. August 2011 um 10:10 Uhr
-
Ich möchte weitere Elemente laden, nachdem 10 Elemente gescrollt wurden. aber ich bemerke, dass das Laden beginnt, bevor das 10. Element sichtbar ist, dh am 9. Element. Wie kann man das stoppen?
– Atul Bhardwaj
31. Oktober 2012 um 6:44 Uhr
oikonomopo
Bei Ognyan Bankov GitHub
Ich habe eine einfache und funktionierende Lösung gefunden!
Es nutzt die Volley HTTP library
Das macht die Vernetzung für Android-Apps einfacher und vor allem schneller. Volley ist über das offene AOSP-Repository verfügbar.
Der angegebene Code zeigt:
- ListView, die von paginierten HTTP-Anforderungen gefüllt wird.
- Verwendung von NetworkImageView.
- “Endlose” ListView-Paginierung mit Read-Ahead.
Für zukünftige Konsistenz i Fork Bankovs Repo.
Fernando Camaro
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
– Helfer, um es zu ermöglichen, die Funktionen zu verwenden, ohne SimpleListViewWithLoadingIndicator zu erweitern.
https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/listener/EndlessScrollListener.java
– Listener, der mit dem Laden von Daten beginnt, wenn der Benutzer das Ende der ListView erreicht.
https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/view/SimpleListViewWithLoadingIndicator.java
– Die EndlessListView. Sie können diese Klasse direkt verwenden oder daraus erweitern.
tehcpu
Kann etwas spät sein, aber die folgende Lösung war in meinem Fall sehr nützlich. Alles, was Sie tun müssen, ist in gewisser Weise Ihrer ListView a hinzuzufügen Footer
und dafür erstellen addOnLayoutChangeListener
.
http://developer.android.com/reference/android/widget/ListView.html#addFooterView(android.view.View)
Zum Beispiel:
ListView listView1 = (ListView) v.findViewById(R.id.dialogsList); // Your listView
View 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(new View.OnLayoutChangeListener() {
@Override
public void 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 funktioniert wie ein Zauber.
Der Schlüssel zu diesem Problem besteht darin, das Load-More-Ereignis zu erkennen, eine asynchrone Datenanforderung zu starten und dann die Liste zu aktualisieren. Außerdem wird ein Adapter mit Ladeanzeige und anderen Dekorelementen benötigt. Tatsächlich ist das Problem in einigen Eckfällen sehr kompliziert. Nur ein OnScrollListener
Die Implementierung reicht nicht aus, da die Elemente manchmal den Bildschirm nicht ausfüllen.
Ich habe ein persönliches Paket geschrieben, das endlose Listen unterstützt RecyclerView
und stellen auch eine asynchrone Loader-Implementierung bereit AutoPagerFragment
wodurch es sehr einfach ist, Daten aus einer mehrseitigen Quelle zu erhalten. Es kann jede gewünschte Seite in a laden RecyclerView
auf einem benutzerdefinierten Ereignis, nicht nur die nächste Seite.
Hier ist die Adresse: https://github.com/SphiaTower/AutoPagerRecyclerManager
-
Die Verbindung ist unterbrochen.
– DSlomer64
3. September 2017 um 23:02 Uhr
Ich empfehle den EndlessAdapter von CommonWare: github.com/commonsguy/cwac-endless. Ich habe es aus dieser Antwort auf eine andere Frage gefunden: stackoverflow.com/questions/4667064/….
– Tyler Collier
7. Juni 2011 um 5:25 Uhr
Ich brauche dasselbe. Kann jemand helfen?..stackoverflow.com/questions/28122304/…
– Benutzer4050065
30. Januar 2015 um 4:00 Uhr