381 Stimmen

Wie implementiere ich eine endlose Liste mit RecyclerView?

Ich möchte ListView in RecyclerView ändern. Ich möchte das onScroll des OnScrollListener in RecyclerView verwenden, um festzustellen, ob ein Benutzer ans Ende der Liste gescrollt ist.

Wie kann ich feststellen, ob ein Benutzer ans Ende der Liste gescrollt ist, damit ich neue Daten von einem REST-Dienst abrufen kann?

3voto

roghayeh hosseini Punkte 655
  1. Erstellen Sie eine abstrakte Klasse und erweitern Sie RecyclerView.OnScrollListener

    public abstract class EndlessRecyclerOnScrollListener extends RecyclerView.OnScrollListener {
    private int previousTotal = 0;
    private boolean loading = true;
    private int visibleThreshold;
    private int firstVisibleItem, visibleItemCount, totalItemCount;
    private RecyclerView.LayoutManager layoutManager;
    
    public EndlessRecyclerOnScrollListener(RecyclerView.LayoutManager layoutManager, int visibleThreshold) {
    this.layoutManager = layoutManager; this.visibleThreshold = visibleThreshold;
    }
    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
    super.onScrolled(recyclerView, dx, dy);
    
    visibleItemCount = recyclerView.getChildCount();
    totalItemCount = layoutManager.getItemCount();
    firstVisibleItem = ((LinearLayoutManager)layoutManager).findFirstVisibleItemPosition();
    
    if (loading) {
        if (totalItemCount > previousTotal) {
            loading = false;
            previousTotal = totalItemCount;
        }
    }
    if (!loading && (totalItemCount - visibleItemCount) <= (firstVisibleItem + visibleThreshold)) {
        onLoadMore();
        loading = true;
    }
      }
    
    public abstract void onLoadMore();}
  2. Fügen Sie in der Aktivität (oder im Fragment) einen addOnScrollListener zum RecyclerView hinzu

    LinearLayoutManager mLayoutManager = new LinearLayoutManager(this);
    recyclerView.setLayoutManager(mLayoutManager);
    recyclerView.addOnScrollListener(new EndlessRecyclerOnScrollListener(mLayoutManager, 3) {
        @Override
        public void onLoadMore() {
            //TODO
            ...
        }
    });

3voto

sergej shafarenka Punkte 19870

Ich würde versuchen, den verwendeten LayoutManager (z.B. LinearLayoutManager) zu erweitern und die Methode scrollVerticallyBy() zu überschreiben. Zuerst würde ich zuerst super aufrufen und dann den zurückgegebenen Integer-Wert überprüfen. Wenn der Wert gleich 0 ist, wurde eine untere oder obere Grenze erreicht. Dann würde ich die Methode findLastVisibleItemPosition() verwenden, um herauszufinden, welche Grenze erreicht ist und bei Bedarf mehr Daten laden. Nur eine Idee.

Zusätzlich können Sie sogar Ihren Wert aus dieser Methode zurückgeben, um Überschreiten und die Anzeige eines "Laden"-Indikators zu ermöglichen.

3voto

speedynomads Punkte 2602

Ich habe eine Implementierung des unendlichen Scrollens mit dieser Logik in der onBindViewHolder-Methode meiner RecyclerView.Adapter-Klasse erreicht.

if (position == mItems.size() - 1 && mCurrentPage <= mTotalPageCount) {
    if (mCurrentPage == mTotalPageCount) {
        mLoadImagesListener.noMorePages();
    } else {
        int newPage = mCurrentPage + 1;
        mLoadImagesListener.loadPage(newPage);
    }
}

Mit diesem Code wird, wenn das RecyclerView das letzte Element erreicht, die aktuelle Seite erhöht und über ein Interface Rückrufe ausgeführt, das dafür verantwortlich ist, weitere Daten aus der API zu laden und die neuen Ergebnisse dem Adapter hinzuzufügen.

Sollte das nicht klar sein, kann ich ein umfangreicheres Beispiel posten?

3voto

walkingice Punkte 111

Mein Weg, um das Laden von Ereignissen zu erkennen, besteht nicht darin, zu erkennen, ob gescrollt wird, sondern zu überwachen, ob die letzte Ansicht angehängt wurde. Wenn die letzte Ansicht angehängt wurde, betrachte ich es als Zeitpunkt zum Laden weiterer Inhalte.

class MyListener implements RecyclerView.OnChildAttachStateChangeListener {
    RecyclerView mRecyclerView;

    MyListener(RecyclerView view) {
        mRecyclerView = view;
    }

    @Override
    public void onChildViewAttachedToWindow(View view) {

    RecyclerView.Adapter adapter = mRecyclerView.getAdapter();
    RecyclerView.LayoutManager mgr = mRecyclerView.getLayoutManager();
    int adapterPosition = mgr.getPosition(view);

    if (adapterPosition == adapter.getItemCount() - 1) {
        // letzte Ansicht wurde angehängt
        loadMoreContent();
    }

    @Override
    public void onChildViewDetachedFromWindow(View view) {}
}

3voto

nonybrighto Punkte 7364

Es gibt eine benutzerfreundliche Bibliothek dafür mit dem Namen paginieren. Unterstützt sowohl ListView als auch RecyclerView (LinearLayout, GridLayout und StaggeredGridLayout).

Hier ist der Link zum Projekt auf Github

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X