How to find out if ListView has scrolled to top Most position?

My friends, combining Graeme's answer with the onScroll method...

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

edit

See comments below as to why, especially on different API versions (esp later ones), this isn't a foolproof way to see if you're list is at the top (padding etc). However, it does give you a start for a solution on devices below API 14:

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

As far as my implementation years ago - this worked perfectly at the time.


I know this question is old, but it shows up top in Google search results. There is a new method introduced in API level 14 that gives exactly what we needed:

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

For older platforms one can use similar static methods of ViewCompat in the v4 support library. See edit below.

Unlike Graeme's method, this method is immune of problems caused by the internal view reuse of ListView and/or header offset.

Edit: final solution

I've found a method in the source code of SwipeRefreshLayout that handles this. It can be rewritten as:

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

You may need to add custom logic if the passed-in view is a custom view.


You will need to check what is the first visible position then applying Graeme's solution to see if the first visible listview item is at the top position.

Something like lv.getFirstVisiblePosition() == 0 && (lv.getChildCount() == 0 || lv.getChildAt(0).getTop() == 0)

Tags:

Android