Vamsi Challa
Vamsi Challa

Reputation: 11109

Recyclerview StaggeredGridLayoutManager - Find last visible item

I am using a Recyclerview with StaggeredGridLayoutManager with Endless Scroll. I want to do a network call when the last item of the list is visible to the user. So here is my code:

   public RecyclerViewAdapter(Context context) {

            Log.d(Const.DEBUG, "RecyclerViewAdapter Constructor()");

            this.context = context;

            final StaggeredGridLayoutManager staggeredGridLayoutManager = (StaggeredGridLayoutManager) recyclerView.getLayoutManager();

            recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
                @Override
                public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                    super.onScrolled(recyclerView, dx, dy);

                    totalItemCount = staggeredGridLayoutManager.getItemCount();
                    lastVisibleItems = staggeredGridLayoutManager.findLastVisibleItemPositions(new int[mStaggeredLayoutManager.getSpanCount()]);

                    Log.d(Const.DEBUG, "LastVisibleItems: " + Arrays.toString(lastVisibleItems));
                    Log.d(Const.DEBUG, "LastVisibleItems Count: " + lastVisibleItems.length);

                    if (staggeredGridLayoutManager.getSpanCount() == 1) {
                        lastVisibleItem = lastVisibleItems[0];
                    } else if (staggeredGridLayoutManager.getSpanCount() == 2) {
                        lastVisibleItem = Math.max(lastVisibleItems[0], lastVisibleItems[1]);
                    } else if (staggeredGridLayoutManager.getSpanCount() == 3) {
                        lastVisibleItem = Math.max(Math.max(lastVisibleItems[0], lastVisibleItems[1]), lastVisibleItems[2]);
                    }


                    if (!isRefreshing && (totalItemCount <= lastVisibleItem + visibleThreshold)) {

                        Log.d(Const.DEBUG, "isRefreshing: " + isRefreshing);
                        Log.d(Const.DEBUG, "totalItemCount: " + totalItemCount);
                        Log.d(Const.DEBUG, "lastVisibileItem: " + lastVisibleItem);
                        Log.d(Const.DEBUG, "visibileThreshold: " + visibleThreshold);

                        Log.d(Const.DEBUG, "calling LoadMore()");

                        if (mIOnLoadMoreListener != null) {
                            mIOnLoadMoreListener.onLoadMore();
                        }

                        isRefreshing = true;
                    }
                }
            });

        }

I get 9 values from server on first call. So, when i move to the last index[8], the lastVisibleItem will be 8 and visibleThreshold is 1, totalItemCount is 9 and so the next network call should happen. What is actually happening now, is, when the screen loads for the first time, the lastVisibleItem should be 1 or 2, but its returning 8, and as a result, the loadMore() is getting called.

Logcat:

D/xx: Items Count: 9
D/xx: LastVisibleItems: [8]
03-22 15:22:52.772 5957-5957/codsiga.com.xx D/xx: LastVisibleItems Count: 1
03-22 15:22:52.772 5957-5957/codsiga.com.xx D/xx: isRefreshing: false
03-22 15:22:52.772 5957-5957/codsiga.com.xx D/xx: totalItemCount: 9
03-22 15:22:52.772 5957-5957/codsiga.com.xx D/xx: lastVisibileItem: 8
03-22 15:22:52.772 5957-5957/codsiga.com.xx D/xx: visibileThershold: 1
03-22 15:22:52.772 5957-5957/codsiga.com.xx D/xx: calling LoadMore()
03-22 15:22:52.772 5957-5957/codsiga.com.xx D/xx: onLoadMore()
03-22 15:22:52.798 5957-5957/codsiga.com.xx D/xx: getDataFromServer()

What is wrong in the above code? Let me know if you need anything else. The same code worked well before.

Upvotes: 3

Views: 5457

Answers (3)

Vishal Nagvadiya
Vishal Nagvadiya

Reputation: 1278

following code is work for me :

//return true if it's last item visited
 private boolean isLastItemDisplaying(RecyclerView recyclerView) {
    if (recyclerView.getAdapter().getItemCount() != 0) {
        //int lastVisibleItemPosition = ((StaggeredGridLayoutManager)recyclerView.getLayoutManager()).findLastVisibleItemPositions();
        int[] lastVisibleItemPositions = ((StaggeredGridLayoutManager) Objects.requireNonNull(recyclerView.getLayoutManager())).findLastVisibleItemPositions(null);
        // get maximum element within the list
        int lastVisibleItemPosition = getLastVisibleItem(lastVisibleItemPositions);
        return lastVisibleItemPosition != RecyclerView.NO_POSITION && lastVisibleItemPosition == recyclerView.getAdapter().getItemCount() - 1;
    }
    return false;
}



//get last item
public int getLastVisibleItem(int[] lastVisibleItemPositions) {
    int maxSize = 0;
    for (int i = 0; i < lastVisibleItemPositions.length; i++) {
        if (i == 0) {
            maxSize = lastVisibleItemPositions[i];
        } else if (lastVisibleItemPositions[i] > maxSize) {
            maxSize = lastVisibleItemPositions[i];
        }
    }
    return maxSize;
}

Upvotes: 3

Sohail Zahid
Sohail Zahid

Reputation: 8149

private void recyclerViewOnScroll(RecyclerView recyclerView, final StaggeredGridLayoutManager staggeredGridLayoutManager) {
        recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);

                if (dy > 0) {

                    totalItemCount = staggeredGridLayoutManager.getItemCount();
                    if (lastPositions == null)
                        lastPositions = new int[staggeredGridLayoutManager.getSpanCount()];
                    lastPositions = staggeredGridLayoutManager.findLastCompletelyVisibleItemPositions(lastPositions);
                    lastVisibleItem = Math.max(lastPositions[0], lastPositions[1]);//findMax(lastPositions);

                    if (!loading && totalItemCount >= 20 && totalItemCount <= (lastVisibleItem + visibleThreshold)) {
                        // End has been reached
                        if (onLoadMoreListener != null) {
                            onLoadMoreListener.onLoadMore();
                        }
                        loading = true;
                    }
                }
            }
        });
    }

Upvotes: 1

Sachin Varma
Sachin Varma

Reputation: 2235

Try this.

    private int pastVisiblesItems, visibleItemCount, totalItemCount;
        private boolean loading = true;   
        private StaggeredGridLayoutManager layoutManager;
        private RecyclerView recyclerView ;

    @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            layoutManager=new StaggeredGridLayoutManager(2,1);
            recyclerView = (RecyclerView) findViewById(R.id.recycler_view);   
            recyclerView.setLayoutManager(layoutManager);
            recycleView.addOnScrollListener(new RecyclerView.OnScrollListener() {
                    @Override
                    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {

                        if (dy > 0) //for vertical scrolling
                        {

                        } else if (dy < 0) {

                        }
                        if (dx > 0)//for horizontal scrolling
                        {
                           visibleItemCount = layoutManager.getChildCount();
                            totalItemCount = layoutManager.getItemCount();
                            pastVisiblesItems = layoutManager.findFirstVisibleItemPosition();

                            if (loading) {
                                if ((visibleItemCount + pastVisiblesItems) >= totalItemCount) {
                                    loading = false;                        
                                    loadMore();  //desired function call                      
                                }
                            }
                        } 
                    }
                });
    }

Please don't forget to make loading=true after the success of API calling.

Hope it may help..

Upvotes: 4

Related Questions