简体   繁体   中英

How can I identify that RecyclerView's last item is visible on screen?

I have one RecyclerView and I added list of data into the RecyclerView . I wanted to add more data in list, when last RecyclerView item is visible on screen. After that I want to make a web service call and update the RecyclerView data. How can I achieve this?

Any suggestions?

There are several ways to accomplish this, but one way would be to use your adapter's onBindViewHolder method:

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        if (position == mData.length - 1) {
            // load more data here.
        }

        /// binding logic
    }

When the bind method is called with the last position of your data source, this is a good indication that the last cell is about to be displayed and a good time to trigger a reload call. You might need to add additional safeguards to the condition to make sure you're not already loading more data, but this should help you get started.

Another option would involve editing your LayoutManager . The idea here is to find the position of the last visible item. If that position is equal to the last item of your dataset, then you should trigger a reload. This call should be done in your LayourManager's onLayoutChildren & scrollVerticallyBy (assuming you use vertical scroll) methods:

    @Override
    public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) {

        final int result = super.scrollVerticallyBy(dy, recycler, state);

        if (findLastVisibleItemPosition() == mData.length - 1) {
           loadMoreData();
        } 

        return result;

    }

    @Override
    public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
        super.onLayoutChildren(recycler, state);

        if (findLastVisibleItemPosition() == mData.length - 1) {
           loadMoreData();
        } 
    }

Same as before, you'll need to make sure you don't trigger a data load more than once, since it's possible this condition will occur more than once.

Hope this helps!

If someone stumble across this post this is a quick and simple tutorial on how to do it:

All you need to do is:

recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
    @Override
    public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
        super.onScrollStateChanged(recyclerView, newState);
    }

    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);
        int visibleItemCount        = lm.getChildCount();
        int totalItemCount          = lm.getItemCount();
        int firstVisibleItemPosition= lm.findFirstVisibleItemPosition();

        // Load more if we have reach the end to the recyclerView
        if ( (visibleItemCount + firstVisibleItemPosition) >= totalItemCount && firstVisibleItemPosition >= 0) {
            loadMoreItems();
        }
    }
});

Then your loadMoreItems() should look something like this:

private void loadMoreItems() {
    // init offset=0 the frist time and increase the offset + the PAGE_SIZE when loading more items
    queryOffset = queryOffset + PAGE_SIZE;
    // HERE YOU LOAD the next batch of items
    List<Items> newItems = loadItems(queryOffset, PAGE_SIZE);

    if (newItems.size() > 0) {
        items.addAll(newItems);
        adapter.notifyDataSetChanged();
    }
}
@Override
public void onBindViewHolder(final RecyclerView.ViewHolderholder, int position) {

    if (!list.isEmpty() || list== null) {

        if (position == (list.size() - 1)) {

            // add new data (add data to list)
            this.notifyDataSetChanged();

        }

    }


}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM