如何识别RecyclerView的最后一项是否在屏幕上可见?

时间:2016-01-26 09:27:40

标签: android android-recyclerview endlessscroll

我有一个RecyclerView,我在RecyclerView中添加了数据列表。当屏幕上显示最后RecyclerView项时,我想在列表中添加更多数据。之后,我想进行Web服务调用并更新RecyclerView数据。我怎样才能做到这一点?

有什么建议吗?

5 个答案:

答案 0 :(得分:18)

有几种方法可以实现这一目标,但有一种方法是使用适配器的onBindViewHolder方法:

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

        /// binding logic
    }

当使用数据源的最后一个位置调用bind方法时,这很好地表明将要显示最后一个单元格并且是触发重新加载调用的好时机。您可能需要在条件中添加其他安全措施,以确保您尚未加载更多数据,但这可以帮助您开始使用。

另一个选项是编辑LayoutManager。这里的想法是找到最后一个可见项目的位置。如果该位置等于数据集的最后一项,则应触发重新加载。此致电应在LayourManager's onLayoutChildren& scrollVerticallyBy(假设您使用垂直滚动)方法:

    @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();
        } 
    }

与以前一样,您需要确保不要多次触发数据加载,因为这种情况可能不止一次发生。

希望这有帮助!

答案 1 :(得分:6)

如果有人偶然发现了这篇文章this 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();
        }
    }
});

然后你的 loadMoreItems()应该是这样的:

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();
    }
}

答案 2 :(得分:0)

看到了许多上述答案,但是我的答案是不同的,它也适用于您的情况。我的方法基于recylerview的滚动状态。保持变量“ check”以下,并且当api响应时,该值仅更新一次。将以下代码放入您的api响应中。如果您只想在每次api调用时处理最后一项。

final boolean[] check = {true};
    recyclerView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
        @Override
        public void onScrollChanged() {
            if (!recyclerView.canScrollVertically(1)) {
                // last item of recylerview reached.
                if (check[0]) {
                    //your code for last reached item
                    scroll_handler.setVisibility(View.GONE);
                }
            } else {
                scroll_handler.setVisibility(View.VISIBLE);
                check[0] = false;
            }
        }
    });

如果您想每次都处理最后一个项目,请按照以下步骤进行操作

recyclerView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
    @Override
    public void onScrollChanged() {
        if (!recyclerView.canScrollVertically(1)) 
            // Bottom of recyler view.
            arrow_img.setRotation(180);
        }
    }
});

答案 3 :(得分:0)

另请参阅Android - Detect when the last item in a RecyclerView is visible

private fun isLastItemVisible(): Boolean {
    val layoutManager = recycler_view.layoutManager
    val position = layoutManager.findLastCompletelyVisibleItemPosition()
    return position >= adapter.itemCount - 1
}

答案 4 :(得分:-1)

@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();

        }

    }


}