如何确定ListView是否已滚动到顶部大多数位置?

时间:2011-09-06 10:25:42

标签: android

我有一个ListView,首先它向下滚动,现在当我们向上滚动时,它会达到最高点。我想检测一下。有什么办法吗?我正在开发api级别的应用程序8.Pls帮助..

10 个答案:

答案 0 :(得分:39)

修改

请参阅下面的评论,为什么,特别是在不同的API版本(尤其是后来的版本)上,这不是一个简单的方法来查看您的列表是否在顶部(填充等)。但是,它确实为您在API 14以下的设备上提供解决方案的开始:

private boolean listIsAtTop()   {   
    if(listView.getChildCount() == 0) return true;
    return listView.getChildAt(0).getTop() == 0;
}

就我多年前的实施情况而言 - 当时这种做法非常完美。

答案 1 :(得分:21)

我知道这个问题很老,但它在Google搜索结果中显示出来。 API级别14中引入了一种新方法,可以提供我们所需的内容:

http://developer.android.com/reference/android/view/View.html#canScrollVertically%28int%29

对于较旧的平台,可以在v4支持库中使用ViewCompat的类似静态方法。请参阅下面的编辑。

与Graeme的方法不同,此方法不受ListView和/或标头偏移的内部视图重用所引起的问题的影响。

编辑:最终解决方案

我在SwipeRefreshLayout的源代码中找到了一个处理此问题的方法。它可以改写为:

public boolean canScrollUp(View view) {
  if (android.os.Build.VERSION.SDK_INT < 14) {
    if (view instanceof AbsListView) {
      final AbsListView absListView = (AbsListView) view;
      return absListView.getChildCount() > 0
          && (absListView.getFirstVisiblePosition() > 0 || absListView
              .getChildAt(0).getTop() < absListView.getPaddingTop());
    } else {
      return view.getScrollY() > 0;
    }
  } else {
    return ViewCompat.canScrollVertically(view, -1);
  }
}

如果传入视图是自定义视图,则可能需要添加自定义逻辑。

答案 2 :(得分:12)

我的朋友们,将 Graeme 的答案与onScroll方法相结合......

listView.setOnScrollListener(new AbsListView.OnScrollListener() {
    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {

    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
        if(firstVisibleItem == 0 && listIsAtTop()){
            swipeRefreshLayout.setEnabled(true);
        }else{
            swipeRefreshLayout.setEnabled(false);
        }
    }
});


private boolean listIsAtTop()   {
    if(listView.getChildCount() == 0) return true;
    return listView.getChildAt(0).getTop() == 0;
}

答案 3 :(得分:2)

您需要检查第一个可见位置,然后应用Graeme的解决方案,看看第一个可见的listview项目是否位于顶部位置。

喜欢的东西 lv.getFirstVisiblePosition()== 0&amp;&amp; (lv.getChildCount()== 0 || lv.getChildAt(0).getTop()== 0)

答案 4 :(得分:1)

您可以使用OnScrollListener通知现在可以看到位置0。使用onScroll方法。

答案 5 :(得分:1)

这个问题已经过时了,但我有一个完美的解决方案,它可能适用于寻找解决方案的人。

int limitRowsBDshow = 10; //size limit your list
listViewMessages.setOnScrollListener(new AbsListView.OnScrollListener() {
        int counter = 1;
        int currentScrollState;
        int currentFirstVisibleItem;
        int currentVisibleItemCount;
        int currentTotalItemCount;


        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {
            this.currentScrollState = scrollState;
            this.isScrollCompleted();
        }

        @Override
        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

            this.currentFirstVisibleItem = firstVisibleItem;
            this.currentVisibleItemCount = visibleItemCount;
            this.currentTotalItemCount = totalItemCount;
        }

        private void isScrollCompleted() {
            if (this.currentVisibleItemCount > 0 && this.currentScrollState == SCROLL_STATE_IDLE) {
                /*** detect if there's been a scroll which has completed ***/

                counter++;
                if (currentFirstVisibleItem == 0 && currentTotalItemCount > limitRowsBDshow - 1) {
                     linearLay20msgMas.setVisibility(View.VISIBLE);
                }
            }
        }
    });

这段代码是很久以前发现的(这里是StackOverflow)。但我找不到这个提及

答案 6 :(得分:0)

Graeme的答案很接近,但遗漏了user2036198添加的内容,检查了getFirstVisiblePosition()。 getChildAt(0)不返回列表中第一个项目的第一个视图。 AbsListView实现不为每个位置创建单个视图,并将它们全部保存在内存中。相反,视图回收生效会限制任何时候实例化的视图数量。

修复非常简单:

public boolean canScrollVertically(AbsListView view) {
    boolean canScroll = false;

    if (view != null && view.getChildCount() > 0) {
        // First item can be partially visible, top must be 0 for the item
        canScroll = view.getFirstVisiblePosition() != 0 || view.getChildAt(0).getTop() != 0;
    }

    return canScroll;
}

要获得ICS或更高级别的最佳结果,请始终使用v4支持库中的ViewCompat或View.canScrollVertically()。在较低的API级别使用上述方法,因为ViewCompat总是为ICS下面的canScrollVertically()和canScrollHorizo​​ntally()返回false。

答案 7 :(得分:0)

如果你可以直接扩展ListView,那么你可以使用名为&#34; computeVerticalScrollOffset()&#34;的受保护方法。在覆盖方法内&#34; onScrollChanged()&#34;。

使用该受保护的方法返回0,表示您的ListView现在已到达顶部。

代码段

        listView = new ListView(this){
        @Override
        protected void onScrollChanged(int l, int t, int oldl, int oldt) {
            super.onScrollChanged(l, t, oldl, oldt);

            if( computeVerticalScrollOffset() == 0 ){
                // Reach top
            }
        }

答案 8 :(得分:0)

为时已晚,但是尝试使用它,在RecyclerView中效果很好。 -1检查是否可以滚动到顶部,而1检查它是否可以滚动到底部

class SiteSpider(scrapy.Spider):
    name = "somesite"
    start_urls = ['https://www.somesite.com']

    def start_requests(self):
        parser = CommentParser()
        urls = ['https://www.somesite.com']
        for url in urls:
            yield scrapy.Request(url=url, callback=parser.scrap)

答案 9 :(得分:-1)

lstView.setOnScrollListener(new AbsListView.OnScrollListener() {

            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
                //To change body of implemented methods use File | Settings | File Templates.
                if (0 == firstVisibleItem){
                    Toast.makeText(MyActivity.this, "Scroll to Top ", Toast.LENGTH_SHORT).show();
                }
            }
        });