Detecting the scrolling direction in the adapter (up/down)

て烟熏妆下的殇ゞ 提交于 2019-11-27 06:38:39

Assign an OnScrollListener to your ListView. Create a flag which indicates whether the user is scrolling up or down. Set an appropriate value to the flag by checking if the current first visible item position equals to more or less than the previous first visible item position. Put that check inside onScrollStateChanged().

Sample code:

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 is true or false in getView(), and assign the animations accordingly.

Waza_Be

I ended up by doing this:

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

}

More complex solution (working with long items height in listview)

  1. Create custom listview

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

The accepted answer doesn't really "detect" scrolling up or down. It won't work if the current visible item 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
    }
});

Try this . I hope it 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;

        }
    });

Here's my approach: It gets you more immediate feedback on how much you've scrolled: OnScroll, you can just get the Top position of the first item in your list. It's a pretty reliable to get actual scroll position information immediately.

listView.getChildAt(0).getTop()

I've 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) {


    }

}
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 Listview is going up or down.

General solution that doesn't rely on positions of views/etc. Just check the vertical scroll offset and compare it to the previous scroll offset. If the new value is greater than the old the user is scrolling down, and vice-versa.

// [START check vertical scroll direction]
int oldScrollOffset = 0;

listView.setOnScrollChangeListener(new View.OnScrollChangeListener() {
        @Override
        public void onScrollChange(View view, int i, int i1, int i2, int i3) {

            Boolean scrollDirectionDown;

            int newScrollOffset = listView.computeVerticalScrollOffset();

            if (newScrollOffset > oldScrollOffset) {
                scrollDirectionDown = true;
            } else {
                scrollDirectionDown = false;
            }

            oldScrollOffset = newScrollOffset;

            if (scrollDirectionDown) {
                // Update accordingly for scrolling down
                Log.d(TAG, "scrolling down");
            } else {
                // Update accordingly for scrolling up
                Log.d(TAG, "scrolling up");
            }

    });
// [END check vertical scroll direction]
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!