我想把ListView改为RecyclerView。我想在RecyclerView中使用OnScrollListener的onScroll来确定用户是否滚动到列表的末尾。
我如何知道用户是否滚动到列表的末尾以便我可以从REST服务获取新数据?
我想把ListView改为RecyclerView。我想在RecyclerView中使用OnScrollListener的onScroll来确定用户是否滚动到列表的末尾。
我如何知道用户是否滚动到列表的末尾以便我可以从REST服务获取新数据?
当前回答
我会尝试扩展使用的LayoutManager(例如LinearLayoutManager)和覆盖scrollVerticallyBy()方法。首先,我会先调用super,然后检查返回的整数值。如果值等于0,则到达底部或顶部边界。然后我将使用findLastVisibleItemPosition()方法来找出到达哪个边界,并在需要时加载更多数据。只是一个想法。
此外,您甚至可以从该方法中返回您的值,允许滚动并显示“loading”指示器。
其他回答
试试下面:
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.LayoutManager;
/**
* Abstract Endless ScrollListener
*
*/
public abstract class EndlessScrollListener extends
RecyclerView.OnScrollListener {
// The minimum amount of items to have below your current scroll position
// before loading more.
private int visibleThreshold = 10;
// The current offset index of data you have loaded
private int currentPage = 1;
// True if we are still waiting for the last set of data to load.
private boolean loading = true;
// The total number of items in the data set after the last load
private int previousTotal = 0;
private int firstVisibleItem;
private int visibleItemCount;
private int totalItemCount;
private LayoutManager layoutManager;
public EndlessScrollListener(LayoutManager layoutManager) {
validateLayoutManager(layoutManager);
this.layoutManager = layoutManager;
}
public EndlessScrollListener(int visibleThreshold,
LayoutManager layoutManager, int startPage) {
validateLayoutManager(layoutManager);
this.visibleThreshold = visibleThreshold;
this.layoutManager = layoutManager;
this.currentPage = startPage;
}
private void validateLayoutManager(LayoutManager layoutManager)
throws IllegalArgumentException {
if (null == layoutManager
|| !(layoutManager instanceof GridLayoutManager)
|| !(layoutManager instanceof LinearLayoutManager)) {
throw new IllegalArgumentException(
"LayoutManager must be of type GridLayoutManager or LinearLayoutManager.");
}
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
visibleItemCount = recyclerView.getChildCount();
totalItemCount = layoutManager.getItemCount();
if (layoutManager instanceof GridLayoutManager) {
firstVisibleItem = ((GridLayoutManager) layoutManager)
.findFirstVisibleItemPosition();
} else if (layoutManager instanceof LinearLayoutManager) {
firstVisibleItem = ((LinearLayoutManager) layoutManager)
.findFirstVisibleItemPosition();
}
if (loading) {
if (totalItemCount > previousTotal) {
loading = false;
previousTotal = totalItemCount;
}
}
if (!loading
&& (totalItemCount - visibleItemCount) <= (firstVisibleItem + visibleThreshold)) {
// End has been reached do something
currentPage++;
onLoadMore(currentPage);
loading = true;
}
}
// Defines the process for actually loading more data based on page
public abstract void onLoadMore(int page);
}
我刚试了一下:
final LinearLayoutManager rvLayoutManager = new LinearLayoutManager(this);
rvMovieList = (RecyclerView) findViewById(R.id.rvMovieList);
rvMovieList.setLayoutManager(rvLayoutManager);
adapter = new MovieRecyclerAdapter(this, movies);
rvMovieList.setAdapter(adapter);
adapter.notifyDataSetChanged();
rvMovieList.addOnScrollListener(new OnScrollListener() {
boolean loading = true;
int pastVisiblesItems, visibleItemCount, totalItemCount;
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
visibleItemCount = rvLayoutManager.getChildCount();
totalItemCount = rvLayoutManager.getItemCount();
pastVisiblesItems = rvLayoutManager.findFirstVisibleItemPosition();
int lastitem = visibleItemCount + pastVisiblesItems;
if ( lastitem == totalItemCount
&& page < total_pages
&& !keyword.equals("") ) {
// hit bottom ..
String strnext;
if (page == total_pages - 1) {
int last = total_results - (page * 20);
strnext = String.format(getResources().getString(R.string.next), last);
} else {
strnext = String.format(getResources().getString(R.string.next), 20);
}
btNext.setText(strnext);
btNext.setVisibility(View.VISIBLE);
} else {
btNext.setVisibility(View.INVISIBLE);
}
if(pastVisiblesItems == 0 && page > 1){
// hit top
btPrev.setVisibility(View.VISIBLE);
} else {
btPrev.setVisibility(View.INVISIBLE);
}
}
});
我搞不清楚在哪里加载真或假,所以我试图删除它,这段代码工作如我所料。
我会尝试扩展使用的LayoutManager(例如LinearLayoutManager)和覆盖scrollVerticallyBy()方法。首先,我会先调用super,然后检查返回的整数值。如果值等于0,则到达底部或顶部边界。然后我将使用findLastVisibleItemPosition()方法来找出到达哪个边界,并在需要时加载更多数据。只是一个想法。
此外,您甚至可以从该方法中返回您的值,允许滚动并显示“loading”指示器。
我让你接近我。对我来说没问题。
我希望这对你有所帮助。
/**
* Created by Daniel Pardo Ligorred on 03/03/2016.
*/
public abstract class BaseScrollListener extends RecyclerView.OnScrollListener {
protected RecyclerView.LayoutManager layoutManager;
public BaseScrollListener(RecyclerView.LayoutManager layoutManager) {
this.layoutManager = layoutManager;
this.init();
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
this.onScroll(recyclerView, this.getFirstVisibleItem(), this.layoutManager.getChildCount(), this.layoutManager.getItemCount(), dx, dy);
}
private int getFirstVisibleItem(){
if(this.layoutManager instanceof LinearLayoutManager){
return ((LinearLayoutManager) this.layoutManager).findFirstVisibleItemPosition();
} else if (this.layoutManager instanceof StaggeredGridLayoutManager){
int[] spanPositions = null; //Should be null -> StaggeredGridLayoutManager.findFirstVisibleItemPositions makes the work.
try{
return ((StaggeredGridLayoutManager) this.layoutManager).findFirstVisibleItemPositions(spanPositions)[0];
}catch (Exception ex){
// Do stuff...
}
}
return 0;
}
public abstract void init();
protected abstract void onScroll(RecyclerView recyclerView, int firstVisibleItem, int visibleItemCount, int totalItemCount, int dx, int dy);
}
没有重复调用,但你滚动。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
}
}
})