[英]Detect when ListView has reached the bottom - onScroll() or onScrollStateChanged()?
This seems a question with many answers already; 这似乎是一个有很多答案的问题; however, I can't find a common approach to this.
但是,我找不到一个通用的方法。 I'm trying to add data to a
ListView
when the bottom is reached; 我正在尝试在到达底部时向
ListView
添加数据; data are retrieved from Internet using an AsyncTask
. 使用
AsyncTask
从Internet检索数据。 ListView
already has an adapter attached to it. ListView
已经附加了一个适配器。
So, searching for a good way to accomplish this, I arrived at two different approaches. 因此,为了找到实现这一目标的好方法,我得出了两种不同的方法。
onScrollStateChanged()
approach, is basically related to this page. onScrollStateChanged()
方法,基本上与此页面相关。 However, it use parameters that don't have correspondence in the actual API. diff
values vary a lot and I don't know how to correctly interpet the expression. diff
值变化很大,我不知道如何正确地插入表达式。 Also, I don't know how to fix an offset from which I can start to retrieving data; onScroll()
approach, that is used in this answer or, in a different way, in this code. onScroll()
方法,在本答案中使用,或者以不同的方式在此代码中使用。 I tried adapting the last of the two codes, but it cause many problems and the data are loaded even if we don't reach the bottom of the list. So, what approach is best? 那么,最好的方法是什么? When and why should I prefer one or the other?
何时以及为什么我更喜欢其中一个? Which of the two should I use in my case?
在我的情况下,我应该使用哪两个?
Here's some code for my suggested third approach, which I use in my own projects. 这是我建议的第三种方法的一些代码,我在自己的项目中使用它。 I use the adapter's
getView
method to detect when the end of the list has been reached. 我使用适配器的
getView
方法来检测何时到达列表的末尾。
public View getView(int position, View convertView, ViewGroup parent) {
// handle recycling/creating/initializing view
if(reachedEndOfList(position)) loadMoreData();
return convertView;
}
private boolean reachedEndOfList(int position) {
// can check if close or exactly at the end
return position == getSize() - 1;
}
private void loadMoreData() {
// Perhaps set flag to indicate you're loading and check flag before proceeding with AsyncTask or whatever
}
You can use an adapter to detect when the listview has been scrolled to its bottom as @darnmason has done in the accepted answer above, but I discovered that sometimes when the list is scrolled very fast, the getView method might not finish processing the last position in the adapter last...maybe because it was still rendering some earlier position. 您可以使用适配器检测列表视图何时滚动到底部,因为@darnmason在上面接受的答案中已完成,但我发现有时当列表滚动得非常快时,getView方法可能无法完成处理最后一个位置在适配器的最后...也许是因为它仍然呈现一些较早的位置。
This annoying effect caused a button that was to fade into view when I scrolled to the bottom of the list to sometimes fail to render. 当我滚动到列表底部有时无法渲染时,这种恼人的效果导致一个淡入视图的按钮。
Here is the solution with the annoying effect, which in principle is similar to @darnmason's solution: 这是具有烦人效果的解决方案,原则上类似于@darnmason的解决方案:
public abstract class MyAdapter extends BaseAdapter {
public View getView(int position, View convertView, ViewGroup parent) {
//your code for getView here...
if(position == this.getCount() - 1){
onScrollToBottom(position);
}
else{
onScrollAwayFromBottom(position);
}
return convertView;
}
public abstract void onScrollToBottom(int bottomIndex);
public abstract void onScrollAwayFromBottom(int currentIndex);
}
This solution detects when the list is scrolled to the bottom and when it is scrolled away from the bottom. 此解决方案检测列表何时滚动到底部以及何时滚动远离底部。
To eliminate the annoying effect, simply modify as follows: 要消除恼人的效果,只需修改如下:
public abstract class MyAdapter extends BaseAdapter {
public View getView(int position, View convertView, ViewGroup parent) {
//your code for getView here...
if(position == this.getCount() - 1){
onScrollToBottom(position);
}
else{
AdapterView adapterView = (AdapterView) parent;
int count = adapterView.getCount();
if(adapterView.getLastVisiblePosition() == count - 1){
//The adapter was faking it, it is already at the bottom!
onScrollToBottom(count - 1);
}
else {
//Honestly! The adapter is truly not at the bottom.
onScrollAwayFromBottom(position);
}
}
return convertView;
}
public abstract void onScrollToBottom(int bottomIndex);
public abstract void onScrollAwayFromBottom(int currentIndex);
}
Now call your adapter as you normally would, like this: 现在像往常一样调用适配器,如下所示:
MyAdapter adapter = new MyAdapter(){
@Override
public void onScrollToBottom(int bottomIndex) {
/*loadMore is a button that fades into view when you are not at the bottom of the list so you can tap and load more data*/
loadMore.show();
}
@Override
public void onScrollAwayFromBottom(int currentIndex) {
/*loadMore is a button that fades out of view when you are not at the bottom of the list*/
loadMore.hide();
}
}
When implemented this way, the adapter becomes very efficient at detecting when the list has been scrolled to its bottom. 以这种方式实现时,适配器在检测列表何时滚动到底部时非常有效。
All it needed was a little cooperation from the list! 所需要的只是列表中的一点合作!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.