本文翻译自:How to implement endless list with RecyclerView?
I would like to change ListView
to RecyclerView
. 我想将ListView
更改为RecyclerView
。 I want to use the onScroll
of the OnScrollListener
in RecyclerView
to determine if a user scrolled to the end of the list. 我想在RecyclerView
使用OnScrollListener
的onScroll
来确定用户是否滚动到列表的末尾。
How do I know if a user scrolls to the end of the list so that I can fetch new data from a REST service? 我如何知道用户是否滚动到列表的末尾,以便可以从REST服务获取新数据?
#1楼
参考:https://stackoom.com/question/1nN51/如何使用RecyclerView实现无尽列表
#2楼
OK, I did it by using the onBindViewHolder method of RecyclerView.Adapter. 好的,我通过使用RecyclerView.Adapter的onBindViewHolder方法做到了。
Adapter: 适配器:
public interface OnViewHolderListener {
void onRequestedLastItem();
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
...
if (position == getItemCount() - 1) onViewHolderListener.onRequestedLastItem();
}
Fragment (or Activity) : 片段 (或活动) :
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
contentView = inflater.inflate(R.layout.comments_list, container, false);
recyclerView = (RecyclerView) mContentView.findViewById(R.id.my_recycler_view);
adapter = new Adapter();
recyclerView.setAdapter(adapter);
...
adapter.setOnViewHolderListener(new Adapter.OnViewHolderListener() {
@Override
public void onRequestedLastItem() {
//TODO fetch new data from webservice
}
});
return contentView;
}
#3楼
I would try to extend used LayoutManager
(eg LinearLayoutManager
) and override scrollVerticallyBy()
method. 我会尝试扩展使用的LayoutManager
(例如LinearLayoutManager
)并重写scrollVerticallyBy()
方法。 Firstly, I would call super
first and then check returned integer value. 首先,我先调用super
,然后检查返回的整数值。 If the value equals to 0
then a bottom or a top border is reached. 如果该值等于0
则到达底部或顶部边界。 Then I would use findLastVisibleItemPosition()
method to find out which border is reached and load more data if needed. 然后,我将使用findLastVisibleItemPosition()
方法找出到达哪个边界,并在需要时加载更多数据。 Just an idea. 只是一个主意。
In addition, you can even return your value from that method allowing overscroll and showing "loading" indicator. 另外,您甚至可以从该方法返回值,从而允许过度滚动并显示“正在加载”指示器。
#4楼
Make these variables. 进行这些变量。
private int previousTotal = 0;
private boolean loading = true;
private int visibleThreshold = 5;
int firstVisibleItem, visibleItemCount, totalItemCount;
Set on Scroll for recycler view. 在滚动条上设置以查看回收者视图。
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
visibleItemCount = mRecyclerView.getChildCount();
totalItemCount = mLayoutManager.getItemCount();
firstVisibleItem = mLayoutManager.findFirstVisibleItemPosition();
if (loading) {
if (totalItemCount > previousTotal) {
loading = false;
previousTotal = totalItemCount;
}
}
if (!loading && (totalItemCount - visibleItemCount)
<= (firstVisibleItem + visibleThreshold)) {
// End has been reached
Log.i("Yaeye!", "end called");
// Do something
loading = true;
}
}
});
Note : Make sure you are using
LinearLayoutManager
as layout manager forRecyclerView
. 注意:确保将LinearLayoutManager
用作RecyclerView
布局管理器。
LinearLayoutManager mLayoutManager;
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
and for a grid 和一个网格
GridLayoutManager mLayoutManager;
mLayoutManager = new GridLayoutManager(getActivity(), spanCount);
mRecyclerView.setLayoutManager(mLayoutManager);
Have fun with your endless scrolls !! 与您无尽的滚动乐趣! ^.^ ^。^
Update : mRecyclerView. 更新: mRecyclerView。
setOnScrollListener()is deprecated just replace withmRecyclerView.addOnScrollListener()
and the warning will be gone!setOnScrollListener()仅仅是弃用替换mRecyclerView.addOnScrollListener()
并警告将会消失! You can read more from this SO question . 您可以从这个SO问题中了解更多信息。
Since Android now officially support Kotlin, here is an update for the same - 由于Android现在已正式支持Kotlin,因此以下是该更新:
Make OnScrollListener 使OnScrollListener
class OnScrollListener(val layoutManager: LinearLayoutManager, val adapter: RecyclerView.Adapter<RecyclerAdapter.ViewHolder>, val dataList: MutableList<Int>) : RecyclerView.OnScrollListener() {
var previousTotal = 0
var loading = true
val visibleThreshold = 10
var firstVisibleItem = 0
var visibleItemCount = 0
var totalItemCount = 0
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
visibleItemCount = recyclerView.childCount
totalItemCount = layoutManager.itemCount
firstVisibleItem = layoutManager.findFirstVisibleItemPosition()
if (loading) {
if (totalItemCount > previousTotal) {
loading = false
previousTotal = totalItemCount
}
}
if (!loading && (totalItemCount - visibleItemCount) <= (firstVisibleItem + visibleThreshold)) {
val initialSize = dataList.size
updateDataList(dataList)
val updatedSize = dataList.size
recyclerView.post { adapter.notifyItemRangeInserted(initialSize, updatedSize) }
loading = true
}
}
}
and add it to your RecyclerView like this 并像这样将其添加到您的RecyclerView中
recyclerView.addOnScrollListener(OnScrollListener(layoutManager, adapter, dataList))
For a full code example, feel free to refer this Github repo . 有关完整的代码示例,请随时参考此Github存储库 。
#5楼
Thanks to @Kushal and this is how I implemented it 感谢@Kushal,这就是我实现它的方式
private boolean loading = true;
int pastVisiblesItems, visibleItemCount, totalItemCount;
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener()
{
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy)
{
if(dy > 0) //check for scroll down
{
visibleItemCount = mLayoutManager.getChildCount();
totalItemCount = mLayoutManager.getItemCount();
pastVisiblesItems = mLayoutManager.findFirstVisibleItemPosition();
if (loading)
{
if ( (visibleItemCount + pastVisiblesItems) >= totalItemCount)
{
loading = false;
Log.v("...", "Last Item Wow !");
//Do pagination.. i.e. fetch new data
}
}
}
}
});
Don't forget to add 不要忘记添加
LinearLayoutManager mLayoutManager;
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
#6楼
I achieved an infinite scrolling type implementation using this logic in the onBindViewHolder
method of my RecyclerView.Adapter
class. 我在RecyclerView.Adapter
类的onBindViewHolder
方法中使用此逻辑实现了无限滚动类型的实现。
if (position == mItems.size() - 1 && mCurrentPage <= mTotalPageCount) {
if (mCurrentPage == mTotalPageCount) {
mLoadImagesListener.noMorePages();
} else {
int newPage = mCurrentPage + 1;
mLoadImagesListener.loadPage(newPage);
}
}
With this code when the RecyclerView gets to the last item, it increments the current page and callbacks on an interface which is responsible for loading more data from the api and adding the new results to the adapter. 使用此代码,当RecyclerView到达最后一项时,它将增加当前页面和接口上的回调,该接口负责从api加载更多数据并将新结果添加到适配器。
I can post more complete example if this isn't clear? 如果不清楚,我可以发布更完整的示例吗?