How to detect if a listview is scrolling up or dow

2019-01-12 03:14发布

问题:

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!

回答1:

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)
            {
                Log.i("SCROLLING DOWN","TRUE");
            }
            if(mLastFirstVisibleItem>firstVisibleItem)
            {
                Log.i("SCROLLING UP","TRUE");
            }
            mLastFirstVisibleItem=firstVisibleItem;

        }
    });


回答2:

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() {...});


回答3:

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


回答4:

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.



回答5:

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


回答6:

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