How to detect if a listview is scrolling up or down in android?
Asked Answered
A

6

10

Is there a way to identify if listview is being scroll up or down?

OnScrollListener doens't help me in this case.

Thanks in advance!

Ambivert answered 9/3, 2012 at 6:30 Comment(3)
exactly what do you want? can u plz explain more...Michamichael
I want to make some code when the list is scrolling up, and make other code when the list is scrolling down. hence, I want to detect if it's scrolling up or downAmbivert
See this #6358928Aulic
C
17

this is a simple implementation:

lv.setOnScrollListener(new OnScrollListener() {

        private int mLastFirstVisibleItem;

        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState){}

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

            if(mLastFirstVisibleItem < firstVisibleItem){
                // Scrolling down
            }
            if(mLastFirstVisibleItem > firstVisibleItem){
                // scrolling up
            }
            mLastFirstVisibleItem = firstVisibleItem;
        }
    });
Choosy answered 3/6, 2014 at 8:36 Comment(3)
Only useful once the top item is no longer the first item. Won't tell you direction if you scroll back and forth while the same item remains at the top.Totemism
This doesn't work perfect when the item has a large height.Sallyanne
@VahidNajafi so, what is the approach, When the list view larger as well as the items are large heights ?Amalia
W
4

There is a method in ScrollViews that reports the shifting of scrolls. It is called onScrollChanged(). However, it is declared protected, so you must create a wrapper class to gain access. For the usage of the method, please check android docs.

First, create an interface to expose the protected method

public interface OnScrollListener {
void onScrollChanged(int x, int y, int oldx, int oldy);
}

Then, create your wrapper and extend ScrollView

public class ReportingScrollView extends ScrollView {
private OnScrollListener onScrollListener = null;

public ReportingScrollView(Context context) {
    super(context);
}

public ReportingScrollView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
}

public ReportingScrollView(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public void setOnScrollListener(OnScrollListener onScrollListener) {
    this.onScrollListener = onScrollListener;
}

@Override
protected void onScrollChanged(int x, int y, int oldx, int oldy) {
    super.onScrollChanged(x, y, oldx, oldy);
    if (onScrollListener != null) {
        onScrollListener.onScrollChanged(x, y, oldx, oldy);
    }
}
}

Finally, include it in your XML layout like a custom view, and attach listeners like usual.

<your.package.ReportingScrollView />

scrollingandtrolling.setOnScrollListener(new OnScrollListener() {...});
Wimberly answered 9/3, 2012 at 7:15 Comment(1)
This only seems to be called when you fling the list, it's not repeatedly called.Stripteaser
G
2

for whom ever still looking for an answer for kotlin, this works for it

MainListView.setOnScrollListener(object :AbsListView.OnScrollListener {
     // var VisibleItem: Int = 0
      override fun onScroll(p0: AbsListView?, FirstVisibleItem: Int, i2: Int, i3: Int) {
      /*   
      if(VisibleItem < FirstVisibleItem)
      {
      Toast.makeText(applicationContext,"Scrolling Down",Toast.LENGTH_SHORT).show()
          fab.hide()
      }
      if(VisibleItem >FirstVisibleItem)
      {
          fab.show()
          Toast.makeText(applicationContext,"Scrolling Up",Toast.LENGTH_SHORT).show()
      }
          VisibleItem=FirstVisibleItem;
  */
      }
      override fun onScrollStateChanged(p0: AbsListView?, p1: Int) {
          if (p1 == 1) {
              fab.hide()
          } else {
              fab.show()
          }
      }

  })
}

Uncomment to use an alternative method.

Griefstricken answered 18/10, 2017 at 20:26 Comment(0)
O
1

An easy and working solution.

private int lastPosition = -1;

        @Override
        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)
        {
            if(lastPosition == firstVisibleItem)
            {
                return;
            }

            if(firstVisibleItem > lastPosition)
            {
                Logger.print("Going Down");
            }
            else
            {
                Logger.print("Going Up");
            }

            lastPosition = firstVisibleItem;
        }
Orthostichy answered 14/1, 2016 at 11:34 Comment(0)
E
0

The solution given by Some Noob Student is good: you have to create a wrapper to use the protected onScrollChanged(int x, int y, int oldx, int oldy) method, which is triggered more often then the standard AbsListView.OnScrollListener.onScrollStateChanged(AbsListView view, int scrollState).

Unfortunately the onScrollChanged() always returns 0 as parameters, no matter how I scroll, and seems to detect only when the scroll ends, reaching the top or the bottom of the list.

So I used the following code to detect the right direction of the scrolling: it uses the getTop() of the first visible item but uses also its position to understand when the first item is no more visible; during this item transition, the scroll direction is given by the item position itself.

        @Override
        public void onScrollChanged(int x, int y, int oldx, int oldy) {

            if(listView.getChildAt(0) != null) {
                int scrollingDir = NO_SCROLLING;
                int firstChildTop = listView.getChildAt(0).getTop();

                if (listView.getFirstVisiblePosition() == mLastFirstVisiblePosition) {
                    if (mLastFirstChildTop < firstChildTop) {
                        //Scrolling DOWN
                        scrollingDir = SCROLLING_DOWN;
                    } else if (mLastFirstChildTop > firstChildTop) {
                        //Scrolling UP
                        scrollingDir = SCROLLING_UP;
                    }
                } else if(listView.getFirstVisiblePosition() > mLastFirstVisiblePosition) {
                    //Scrolling UP
                    scrollingDir = SCROLLING_UP;
                } else {
                    //Scrolling DOWN
                    scrollingDir = SCROLLING_DOWN;
                }
                mLastFirstVisiblePosition = listView.getFirstVisiblePosition();
                mLastFirstChildTop = firstChildTop;

                switch(scrollingDir) {
                    case SCROLLING_DOWN:
                        //Your DOWN scrolling code here
                        break;

                    case SCROLLING_UP:
                        //Your UP scrolling code here
                        break;

                    default:
                    case NO_SCROLLING:
                        break;
                }
            }
        }
Enjoy answered 16/7, 2014 at 13:13 Comment(0)
C
0
list.setOnScrollListener(new OnScrollListener() {
        int last_item;
        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {

        }

        @Override
        public void onScroll(AbsListView view, int firstVisibleItem,
                int visibleItemCount, int totalItemCount) {
            if(last_item<firstVisibleItem+visibleItemCount-1){
                System.out.println("List is scrolling upwards");
            }
            else if(last_item>firstVisibleItem+visibleItemCount-1){
                System.out.println("List is scrolling downwards");
            }
             last_item = firstVisibleItem+visibleItemCount-1;
        }
    });

Here based on the last visible item i decide whether the list is going up or down

Crissie answered 14/4, 2015 at 12:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.