我如何确定 RecyclerView 最后一项在屏幕上可见?
How can I identify that RecyclerView's last item is visible on screen?
我有一个 RecyclerView
,我在 RecyclerView
中添加了数据列表。当屏幕上显示最后一个 RecyclerView
项时,我想在列表中添加更多数据。之后我想进行网络服务调用并更新 RecyclerView
数据。我怎样才能做到这一点?
有什么建议吗?
一个选项涉及编辑您的 LayoutManager
。这里的想法是找到最后一个可见项目的位置。如果该位置等于数据集的最后一项,那么您应该触发重新加载。
@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();
}
}
或者,您可以通过适配器的 onBindViewHolder
方法执行此操作,尽管这确实有点 "hack":
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (position == mData.length - 1) {
// load more data here.
}
/// binding logic
}
第三个选项是将 OnScrollListener 添加到 RecyclerView。 @velval 在此页面上的回答很好地解释了这一点。
无论您选择哪个选项,您还应该包含代码以防止数据加载逻辑触发太多次(例如,在先前获取更多数据的请求完成和 returns 新数据之前)。
如果有人偶然发现了这个 post 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();
}
}
看到上面的许多答案,但我的答案不同,它也适用于您的情况。我的方法是基于 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);
}
}
});
另见 。
private fun isLastItemVisible(): Boolean {
val layoutManager = recycler_view.layoutManager
val position = layoutManager.findLastCompletelyVisibleItemPosition()
return position >= adapter.itemCount - 1
}
我有一个 RecyclerView
,我在 RecyclerView
中添加了数据列表。当屏幕上显示最后一个 RecyclerView
项时,我想在列表中添加更多数据。之后我想进行网络服务调用并更新 RecyclerView
数据。我怎样才能做到这一点?
有什么建议吗?
一个选项涉及编辑您的 LayoutManager
。这里的想法是找到最后一个可见项目的位置。如果该位置等于数据集的最后一项,那么您应该触发重新加载。
@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();
}
}
或者,您可以通过适配器的 onBindViewHolder
方法执行此操作,尽管这确实有点 "hack":
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (position == mData.length - 1) {
// load more data here.
}
/// binding logic
}
第三个选项是将 OnScrollListener 添加到 RecyclerView。 @velval 在此页面上的回答很好地解释了这一点。
无论您选择哪个选项,您还应该包含代码以防止数据加载逻辑触发太多次(例如,在先前获取更多数据的请求完成和 returns 新数据之前)。
如果有人偶然发现了这个 post 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();
}
}
看到上面的许多答案,但我的答案不同,它也适用于您的情况。我的方法是基于 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);
}
}
});
另见
private fun isLastItemVisible(): Boolean {
val layoutManager = recycler_view.layoutManager
val position = layoutManager.findLastCompletelyVisibleItemPosition()
return position >= adapter.itemCount - 1
}