检测ListView何时到达底部 - onScroll()或onScrollStateChanged()?

时间:2015-01-27 18:23:07

标签: android android-listview android-scroll

这似乎是一个已经有许多答案的问题;但是,我无法找到一个共同的方法。 我到达底部时尝试将数据添加到ListView;使用AsyncTask从Internet检索数据。 ListView已经附加了适配器。

因此,为了找到实现这一目标的好方法,我得出了两种不同的方法。

  1. 第一个是onScrollStateChanged()方法,与this页面基本相关。但是,它使用的参数在实际API中没有对应关系。同时,this链接使用正确的API,但我不知道是否以正确的方式。我尝试了两个链接中的第一个,但它有点像meh。调试应用程序,diff值差异很大,我不知道如何正确地插入表达式。此外,我不知道如何修复我可以开始检索数据的偏移量;我的意思是,我不想在我即将到达底部时,而是在我到达之前执行代码。此外,即使我们滚动到顶部,有时它也会被调用。
  2. 第二个是onScroll()方法,用于this答案,或者以this代码的不同方式使用。我尝试调整两个代码中的最后一个,但它会导致很多问题,即使我们没有到达列表底部,数据也会被加载。
  3. 那么,什么方法最好?何时以及为什么我更喜欢其中一个? 在我的情况下,我应该使用哪两个?

2 个答案:

答案 0 :(得分:17)

这是我建议的第三种方法的一些代码,我在自己的项目中使用它。我使用适配器的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
}

答案 1 :(得分:0)

您可以使用适配器来检测列表视图何时滚动到底部,就像@darnmason在上面接受的答案中所做的那样,但是我发现有时候列表快速滚动时,getView方法可能无法完成处理适配器中的最后一个位置为上一个...也许是因为它仍在呈现一些更早的位置。

这种令人讨厌的效果导致当我滚动到列表底部时有时会无法显示的按钮。

这是具有烦人效果的解决方案,其原理与@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);


}

此解决方案可以检测列表何时滚动到底部以及何时滚动远离底部。

要消除烦人的效果,只需进行如下修改:

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);


}

现在像往常一样呼叫适配器,如下所示:

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();

            }

}

以这种方式实现时,适配器在检测列表何时滚动到其底部时变得非常有效。

需要的只是列表中的一点合作!