Detecting scroll direction in adapter (up / down)

I'm trying to emulate the Google Plus application in my project, as it is now a link.

The listview effect on scrolling is really good, and I would like to do something like this.

I started with LayoutAnimationController http://android-er.blogspot.be/2009/10/listview-and-listactivity-layout.html

LayoutAnimationController controller = AnimationUtils.loadLayoutAnimation( this, R.anim.list_layout_controller); getListView().setLayoutAnimation(controller); 

and this seems bad, because not all elements are animated:

So, I ended up using the getView adapter and using this:

  AnimationSet set = new AnimationSet(true); Animation animation = new AlphaAnimation(0.0f, 1.0f); animation.setDuration(800); set.addAnimation(animation); animation = new TranslateAnimation( Animation.RELATIVE_TO_SELF, 0.0f,Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 1.0f,Animation.RELATIVE_TO_SELF, 0.0f ); animation.setDuration(600); set.addAnimation(animation); row.startAnimation(set); 

The result is amazing, and I'm really happy with it!

Unfortunately, it only works when scrolling from top to bottom of a list!

I want to make it work while scrolling on the other hand, I need to change TranslateAnimation a bit.

So my question is, is there a way to determine if I am scrolling up or down in my adapter?

+13
android listview scroll animation direction
Aug 24 '12 at 18:41
source share
8 answers

Assign OnScrollListener to your ListView . Create a flag indicating whether the user scrolls up or down. Set the appropriate value for the flag by checking if the current position of the first visible element matches more or less than the previous position of the first visible element. Put this check inside onScrollStateChanged() .

Code example:

 private int mLastFirstVisibleItem; private boolean mIsScrollingUp; public void onScrollStateChanged(AbsListView view, int scrollState) { final ListView lw = getListView(); if (view.getId() == lw.getId()) { final int currentFirstVisibleItem = lw.getFirstVisiblePosition(); if (currentFirstVisibleItem > mLastFirstVisibleItem) { mIsScrollingUp = false; } else if (currentFirstVisibleItem < mLastFirstVisibleItem) { mIsScrollingUp = true; } mLastFirstVisibleItem = currentFirstVisibleItem; } } 

Check if mIsScrollingUp true or false in getView() and assigns animation accordingly.

+22
Aug 24 2018-12-18T00:
source share

I ended up with:

 @Override public View getView(int position, View convertView, ViewGroup parent) { Log.i("",position+" - "+lastposition); if (position >= lastposition) animation = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 1.0f, Animation.RELATIVE_TO_SELF, 0.0f); else animation = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, -1.0f, Animation.RELATIVE_TO_SELF, 0.0f); animation.setDuration(600); set.addAnimation(animation); row.startAnimation(set); lastposition = position; } 
+18
Aug 24 '12 at 19:21
source share

More complex solution (working with the height of long elements in the list)

  • Create your own watchlist

     public class ScrollDetectingListView extends ListView { public ScrollDetectingListView(Context context) { super(context); } public ScrollDetectingListView(Context context, AttributeSet attrs) { super(context,attrs); } public ScrollDetectingListView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } //we need this protected method for scroll detection public int getVerticalScrollOffset() { return computeVerticalScrollOffset(); } } 
  • Override onScroll

      listView.setOnScrollListener(new AbsListView.OnScrollListener() { private int mInitialScroll = 0; @Override public void onScrollStateChanged(AbsListView view, int scrollState) { } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { int scrolledOffset = listView.getVerticalScrollOffset(); if (scrolledOffset!=mInitialScroll) { //if scroll position changed boolean scrollUp = (scrolledOffset - mInitialScroll) < 0; mInitialScroll = scrolledOffset; } } }); 
+5
Aug 29 '14 at 8:45
source share

The accepted answer does not really β€œdetect” scrolling up or down. It will not work if the current visible element is really huge. Using onTouchListener is the way to go.

This is the code snippet I used:

 listView.setOnTouchListener(new View.OnTouchListener() { float initialY, finalY; boolean isScrollingUp; @Override public boolean onTouch(View v, MotionEvent event) { int action = MotionEventCompat.getActionMasked(event); switch(action) { case (MotionEvent.ACTION_DOWN): initialY = event.getY(); case (MotionEvent.ACTION_UP): finalY = event.getY(); if (initialY < finalY) { Log.d(TAG, "Scrolling up"); isScrollingUp = true; } else if (initialY > finalY) { Log.d(TAG, "Scrolling down"); isScrollingUp = false; } default: } if (isScrollingUp) { // do animation for scrolling up } else { // do animation for scrolling down } return false; // has to be false, or it will freeze the listView } }); 
+4
May 23 '15 at 16:20
source share

Try it. Hope this helps you. Logic from @Gal Rom answer.

 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
Mar 17 '15 at 5:12
source share

Here's my approach: it gives you more immediate feedback on how much you scroll: OnScroll , you can just get the top position of the first item in your list. It is pretty reliable to get the actual scroll position information right away.

 listView.getChildAt(0).getTop() 
+1
May 6 '13 at 18:25
source share

I used this much simpler solution:

 public class ScrollDetectingListView extends ListView 

...

 setOnScrollListener( new OnScrollListener() { private int mInitialScroll = 0; @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { int scrolledOffset = computeVerticalScrollOffset(); boolean scrollUp = scrolledOffset > mInitialScroll; mInitialScroll = scrolledOffset; } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { } } 
0
May 31 '14 at 13:21
source share
 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; } }); 

Based on the position of the last visible item, I decide whether the Listview goes up or down.

0
Apr 14 '15 at 12:21
source share



All Articles