我想把ListView改为RecyclerView。我想在RecyclerView中使用OnScrollListener的onScroll来确定用户是否滚动到列表的末尾。
我如何知道用户是否滚动到列表的末尾以便我可以从REST服务获取新数据?
我想把ListView改为RecyclerView。我想在RecyclerView中使用OnScrollListener的onScroll来确定用户是否滚动到列表的末尾。
我如何知道用户是否滚动到列表的末尾以便我可以从REST服务获取新数据?
当前回答
下面是一个简单实现无尽滚动RecyclerView的例子,使用一个从各种来源编译的简单库。
在build.gradle中添加这一行
implementation 'com.hereshem.lib:awesomelib:2.0.1'
在活动中创建RecyclerView布局
<com.hereshem.lib.recycler.MyRecyclerView
android:id="@+id/recycler"
app:layoutManager="LinearLayoutManager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
通过传递ViewHolder支持的类来创建一个ViewHolder
public static class EVHolder extends MyViewHolder<Events> {
TextView date, title, summary;
public EVHolder(View v) {
super(v);
date = v.findViewById(R.id.date);
title = v.findViewById(R.id.title);
summary = v.findViewById(R.id.summary);
}
@Override
public void bindView(Events c) {
date.setText(c.date);
title.setText(c.title);
summary.setText(c.summary);
}
}
通过在适配器中传递项目、类和布局来创建项目列表变量和很少行的适配器
List<Events> items = new ArrayList<>();
MyRecyclerView recycler = findViewById(R.id.recycler);
RecyclerViewAdapter adapter = new RecyclerViewAdapter(this, items, EVHolder.class, R.layout.row_event);
recycler.setAdapter(adapter);
ClickListener和LoadMore Listener可以通过以下几行添加
recycler.setOnItemClickListener(new MyRecyclerView.OnItemClickListener() {
@Override
public void onItemClick(int position) {
Toast.makeText(MainActivity.this, "Recycler Item Clicked " + position, Toast.LENGTH_SHORT).show();
}
});
recycler.setOnLoadMoreListener(new MyRecyclerView.OnLoadMoreListener() {
@Override
public void onLoadMore() {
loadData();
}
});
loadData();
数据加载后必须调用此函数
recycler.loadComplete();
当不需要LoadMore时,可以通过调用LoadMore来隐藏布局
recycler.hideLoadMore();
更多的例子可以在这里找到
希望这对你有所帮助。
其他回答
有一个方法public void setOnScrollListener (RecyclerView。OnScrollListener监听器)在https://developer.android.com/reference/android/support/v7/widget/RecyclerView.html#setOnScrollListener%28android.support.v7.widget.RecyclerView.OnScrollListener%29。使用这个
编辑:
在onScrollListener中重写onScrollStateChanged方法并执行此操作
boolean loadMore = firstVisibleItem + visibleItemCount >= totalItemCount;
//loading is used to see if its already loading, you have to manually manipulate this boolean variable
if (loadMore && !loading) {
//end of list reached
}
没有重复调用,但你滚动。fetchData只会在您位于列表的末尾并且有更多数据要获取时调用
关于我的代码: 1.fetchData()每次调用取10个项。 2.isScrolling是一个类成员变量 3.previousTotalCount也是类成员。它存储以前访问过的最后一个项目
recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
if (newState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
isScrolling = true
}
}
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
val visibleItemCount = layoutManager.childCount
val totalItemCount = layoutManager.itemCount
val scrolledOutItems = layoutManager.findFirstVisibleItemPosition()
if (isScrolling && (visibleItemCount + scrolledOutItems == totalItemCount)
&& (visibleItemCount + scrolledOutItems != previousTotalCount)) {
previousTotalCount = totalItemCount
isScrolling = false
fetchData() //fetches 10 new items from Firestore
pagingProgressBar.visibility = View.VISIBLE
}
}
})
我在我的RecyclerView的onBindViewHolder方法中使用此逻辑实现了无限滚动类型。适配器类。
if (position == mItems.size() - 1 && mCurrentPage <= mTotalPageCount) {
if (mCurrentPage == mTotalPageCount) {
mLoadImagesListener.noMorePages();
} else {
int newPage = mCurrentPage + 1;
mLoadImagesListener.loadPage(newPage);
}
}
使用这段代码,当RecyclerView到达最后一项时,它会增加当前页面和接口上的回调,该接口负责从api加载更多数据并将新结果添加到适配器。
我可以张贴更完整的例子,如果这不是很清楚?
我是这样做的,简单而简短:
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener()
{
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy)
{
if(!recyclerView.canScrollVertically(1) && dy != 0)
{
// Load more results here
}
}
});
这个解决方案对我来说非常有效。
//Listener
public abstract class InfiniteScrollListener extendsRecyclerView.OnScrollListener {
public static String TAG = InfiniteScrollListener.class.getSimpleName();
int firstVisibleItem, visibleItemCount, totalItemCount;
private int previousTotal = 0;
private boolean loading = true;
private int visibleThreshold = 1;
private int current_page = 1;
private LinearLayoutManager mLinearLayoutManager;
public InfiniteScrollListener(LinearLayoutManager linearLayoutManager) {
this.mLinearLayoutManager = linearLayoutManager;
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
visibleItemCount = recyclerView.getChildCount();
totalItemCount = mLinearLayoutManager.getItemCount();
firstVisibleItem = mLinearLayoutManager.findFirstVisibleItemPosition();
if (loading) {
if (totalItemCount > previousTotal) {
loading = false;
previousTotal = totalItemCount;
}
}
if (!loading && (totalItemCount - visibleItemCount - firstVisibleItem <= visibleThreshold)) {
current_page++;
onLoadMore(current_page);
loading = true;
}
}
public void resetState() {
loading = true;
previousTotal = 0;
current_page = 1;
}
public abstract void onLoadMore(int current_page);
}
//Implementation into fragment
private InfiniteScrollListener scrollListener;
scrollListener = new InfiniteScrollListener(manager) {
@Override
public void onLoadMore(int current_page) {
//Load data
}
};
rv.setLayoutManager(manager);
rv.addOnScrollListener(scrollListener);