How to implement pagination in RecyclerView on scroll

前端 未结 2 745
礼貌的吻别
礼貌的吻别 2021-01-22 06:13

Recyclerview comes with its own scroll listener which has the following methods :

void onScrollStateChanged(RecyclerView recyclerView, int newState)         


        
相关标签:
2条回答
  • 2021-01-22 06:49

    Here's a scroll listener which implements load more and quick return pattern:

    public abstract class HidingScrollListener extends RecyclerView.OnScrollListener {
    
        private static final float  HIDE_THRESHOLD   = 10;
        private static final float  SHOW_THRESHOLD   = 70;
    
        private int                 mToolbarOffset   = 0;
        private boolean             mControlsVisible = true;
        private int                 mToolbarHeight;
        private int                 mTotalScrolledDistance;
        private int                 previousTotal    = 0;
        private boolean             loading          = true;
        private int                 visibleThreshold = 4;
        int                         firstVisibleItem, visibleItemCount, totalItemCount;
        private LinearLayoutManager layoutManager;
    
        public HidingScrollListener(Context context, LinearLayoutManager layoutManager) {
            mToolbarHeight = Tools.getFooterHeight(context);
            this.layoutManager = layoutManager;
        }
    
        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);
    
            if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                if (mTotalScrolledDistance < mToolbarHeight) {
                    setVisible();
                }
                else {
                    if (mControlsVisible) {
                        if (mToolbarOffset > HIDE_THRESHOLD) {
                            setInvisible();
                        }
                        else {
                            setVisible();
                        }
                    }
                    else {
                        if ((mToolbarHeight - mToolbarOffset) > SHOW_THRESHOLD) {
                            setVisible();
                        }
                        else {
                            setInvisible();
                        }
                    }
                }
            }
    
        }
    
        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
    
            clipToolbarOffset();
            onMoved(mToolbarOffset);
    
            if ((mToolbarOffset < mToolbarHeight && dy > 0) || (mToolbarOffset > 0 && dy < 0)) {
                mToolbarOffset += dy;
            }
            if (mTotalScrolledDistance < 0) {
                mTotalScrolledDistance = 0;
            }
            else {
                mTotalScrolledDistance += dy;
            }
            // for load more
            visibleItemCount = recyclerView.getChildCount();
            totalItemCount = layoutManager.getItemCount();
            firstVisibleItem = layoutManager.findFirstVisibleItemPosition();
    
            if (loading) {
                if (totalItemCount > previousTotal) {
                    loading = false;
                    previousTotal = totalItemCount;
                }
            }
            if (!loading && (totalItemCount - visibleItemCount) <= (firstVisibleItem + visibleThreshold)) {
                // End has been reached
                // Do something
    
                loading = true;
                onLoadMore();
            }
        }
    
        private void clipToolbarOffset() {
            if (mToolbarOffset > mToolbarHeight) {
                mToolbarOffset = mToolbarHeight;
            }
            else if (mToolbarOffset < 0) {
                mToolbarOffset = 0;
            }
        }
    
        private void setVisible() {
            if (mToolbarOffset > 0) {
                onShow();
                mToolbarOffset = 0;
            }
            mControlsVisible = true;
        }
    
        private void setInvisible() {
            if (mToolbarOffset < mToolbarHeight) {
                onHide();
                mToolbarOffset = mToolbarHeight;
            }
            mControlsVisible = false;
        }
    
        public abstract void onMoved(int distance);
    
        public abstract void onShow();
    
        public abstract void onHide();
    
        public abstract void onLoadMore();
    }
    

    And it's implementation is below:

    HidingScrollListener scrollListener = new HidingScrollListener(activity, manager) {
             @Override
             public void onMoved(int distance) {
    
             }
    
             @Override
             public void onShow() {
    
             }
    
             @Override
             public void onHide() {
    
             }
    
             @Override
             public void onLoadMore() {
                // you can do your pagination here.
             }
          };
          mRecyclerView.addOnScrollListener(scrollListener);
    
    0 讨论(0)
  • 2021-01-22 07:02

    Make Next Call at the end of scroll

    There are essentially 3 steps.

    1. Notify when the list is scrolled
    2. Make REST call (for NEXT page)
    3. Add the result in the old list + Notify DataSet change

    CALLBACK

    But first, we need a Callback which would work as a bridge between RecyclerView.Adapter and Activity

    public interface PaginationCallBack{
         public void oadNextPage();
    }
    

    Implement this callback in Your Activity

    class YourActivity extends AppCompatActivity implements PaginationCallBack{
    
         int pageNum = 1;
    
         @Override
         public void loadNextPage(){
               // Your implementation
         }
    }
    

    Initialize Callback in RecyclerView.Adapter

    class YourAdapter extends RecyclerView.Adapter{
    
         private PaginationCallBack paginationCallBack;
    
         public YourAdapter(PaginationCallBack paginationCallBack) {
            this.paginationCallBack = paginationCallBack;
         }
    
    }
    

    STEP 1 Add a condition in onBindViewHolder method and notify with a Callback.

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewholder, int position) {
    
        if(position+1==images.size()){
            paginationCallBack.loadNextPage();  // Callback
        }
    
    }
    

    Step 2: Call NEXT Page

    getImages(++pageNum) // YOUR REST method which page number

    @Override
    public void loadNextPage(){
        getImages(++pageNumber) // REST call with next Page 
    }
    

    Step 3 Add the result in old list and notify datasetChanged

    public void getImages(int pageNum){
    
          List<Images> newResults = //RESTCALL
          imageList.addAll(newResults);
          adapter.updateDataSet(imageList)
    
    }
    

    Where is updateDataSet(imageList) method?

    Write this method inside RecyclerView.Adapter

     public void updateDataSet(List<GalleryMedia> newImages){
    
        if(newImages!=null){
            images = newImages;
        }
    
        notifyDataSetChanged();
    }
    

    Full Code

    RecyclerView Pagination

    Result:

    0 讨论(0)
提交回复
热议问题