ViewPager detect when user is trying to swipe out of bounds

后端 未结 5 1045
生来不讨喜
生来不讨喜 2020-11-27 04:05

I am using the ViewPager consisting of 6 pages to display some data. I want to be able to call a method when the user is at position 0 and tries to swipe to the right (backw

相关标签:
5条回答
  • 2020-11-27 04:15

    How about setting an OnPageChangeListener on your ViewPager? Then you can modify your navigation arrows or whatever in the onPageScrolled.

    viewPager.setOnPageChangeListener(new OnPageChangeListener() {
        @Override
        public void onPageSelected(int position) {
        }
    
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                updateNavigationArrows();
        }
    
        @Override
        public void onPageScrollStateChanged(int state) {
        }
    });
    
    0 讨论(0)
  • 2020-11-27 04:26

    I wonder how it worked for others, it's not working for me.

    onInterceptTouchEvent() only takes ACTION_DOWN event. While onTouchEvent() only takes one event at a time either ACTION_DOWN, ACTION_UP and others.

    I had to override both onInterceptTouchEvent() and onTouchEvent() to make it work properly. The ACTION_DOWN of onInterceptTouchEvent grabs initial X point of touch, and OnTouchEvent grabs final X2 point. Which I compared it to detect swipe direction.

    Get initial X value of the touch:

    float x1 = 0;
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
            switch(ev.getAction() & MotionEventCompat.ACTION_MASK){
            case MotionEvent.ACTION_DOWN:
                x1 = ev.getX();
                break;
            }
            return super.onInterceptTouchEvent(ev);
        }
    

    From tjlian616's code, the onTouchEvent() listens to ACTION_UP and gets it's last X Value. While I've set my current item's value to be 0 to get swipe out at start listener. Compared it and add fired up the listener.

     @Override
     public boolean onTouchEvent(MotionEvent ev){
            if(getCurrentItem()==0){
                final int action = ev.getAction();
                switch(action & MotionEventCompat.ACTION_MASK){
                case MotionEvent.ACTION_MOVE:
                    break;
                case MotionEvent.ACTION_UP:
                    mStartDragX = ev.getX();
                    if (x1<mStartDragX){
                        Log.i("TOUCH: ", "ACTION UP " + x1 + " : " + mStartDragX );
                        mListener.onSwipeOutAtStart();
                    }else{
                        Log.i("TOUCH ELSE : ", "ACTION UP " + x1 + " : " + mStartDragX );
                        mStartDragX = 0;
                    }
                    break;
                }
            }else{
                mStartDragX=0;
            }
            return super.onTouchEvent(ev);
        }    
    
    0 讨论(0)
  • 2020-11-27 04:29

    Extend ViewPager and override onInterceptTouchEvent() like this:

    public class CustomViewPager extends ViewPager {
    
        float mStartDragX;
        OnSwipeOutListener mListener;
    
    
        public void setOnSwipeOutListener(OnSwipeOutListener listener) {
            mListener = listener;
        }
    
    
        @Override
        public boolean onInterceptTouchEvent(MotionEvent ev) {
            float x = ev.getX();
            switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mStartDragX = x;
                break;
            case MotionEvent.ACTION_MOVE:
                if (mStartDragX < x && getCurrentItem() == 0) {
                    mListener.onSwipeOutAtStart();
                } else if (mStartDragX > x && getCurrentItem() == getAdapter().getCount() - 1) {
                    mListener.onSwipeOutAtEnd();
                }
                break;
            }
            return super.onInterceptTouchEvent(ev);
        }
    
        public interface OnSwipeOutListener {
            public void onSwipeOutAtStart();
            public void onSwipeOutAtEnd();
        }
    
    }
    
    0 讨论(0)
  • 2020-11-27 04:33

    Thanks a lot to @Flavio, although i had to do some changes to his code because the callbacks methods were firing twice, also I added code to check if there was any registered listener, to avoid app crashing when there is no listener registered. This is the code I used to make it work, with both onSwipeOutAtStart and onSwipeOutAtEnd:

    public class CustomViewPager extends android.support.v4.view.ViewPager {
    
        float mStartDragX;
        OnSwipeOutListener mOnSwipeOutListener;
    
        public CustomViewPager(Context context) {
            super(context);
        }
    
        public CustomViewPager(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public void setOnSwipeOutListener(OnSwipeOutListener listener) {
            mOnSwipeOutListener = listener;
        }
    
        private void onSwipeOutAtStart() {
            if (mOnSwipeOutListener!=null) {
                mOnSwipeOutListener.onSwipeOutAtStart();
            }
        }
    
        private void onSwipeOutAtEnd() {
            if (mOnSwipeOutListener!=null) {
                mOnSwipeOutListener.onSwipeOutAtEnd();
            }
        }
    
        @Override
        public boolean onInterceptTouchEvent(MotionEvent ev) {
            switch(ev.getAction() & MotionEventCompat.ACTION_MASK){
                case MotionEvent.ACTION_DOWN:
                    mStartDragX = ev.getX();
                    break;
            }
            return super.onInterceptTouchEvent(ev);
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent ev){
    
            if(getCurrentItem()==0 || getCurrentItem()==getAdapter().getCount()-1){
                final int action = ev.getAction();
                float x = ev.getX();
                switch(action & MotionEventCompat.ACTION_MASK){
                    case MotionEvent.ACTION_MOVE:
                        break;
                    case MotionEvent.ACTION_UP:
                        if (getCurrentItem()==0 && x>mStartDragX) {
                            onSwipeOutAtStart();
                        }
                        if (getCurrentItem()==getAdapter().getCount()-1 && x<mStartDragX){
                            onSwipeOutAtEnd();
                        }
                        break;
                }
            }else{
                mStartDragX=0;
            }
            return super.onTouchEvent(ev);
    
        }
    
        public interface OnSwipeOutListener {
            void onSwipeOutAtStart();
            void onSwipeOutAtEnd();
        }
    }
    
    0 讨论(0)
  • 2020-11-27 04:41

    The answer from Flávio Faria doesn't work for me. The only event I get in onInterceptTouchEvent() is ACTION_DOWN event. So I override the onTouchEvent() method to get it work.

    Here is the code. Note that I only have onSwipeOutAtEnd() in the listener. You can add your code to support swiping left on first vier.

    public class CustomViewPager extends ViewPager {
    
    float mStartDragX;
    OnSwipeOutListener mListener;
    
    
    public void setOnSwipeOutListener(OnSwipeOutListener listener) {
        mListener = listener;
    }
    
    @Override
    public boolean onTouchEvent(MotionEvent ev){
        if(getCurrentItem()==getAdapter().getCount()-1){
            final int action = ev.getAction();
            float x = ev.getX();
            switch(action & MotionEventCompat.ACTION_MASK){
            case MotionEvent.ACTION_DOWN:
                mStartDragX = x;
                break;
            case MotionEvent.ACTION_MOVE:
                break;
            case MotionEvent.ACTION_UP:
                if (x<mStartDragX){
                    mListener.onSwipeOutAtEnd();
                }else{
                    mStartDragX = 0;
                }
                break;
            }
        }else{
            mStartDragX=0;
        }
        return super.onTouchEvent(ev);
    }    
    public interface OnSwipeOutListener {
        public void onSwipeOutAtEnd();
    }
    
    0 讨论(0)
提交回复
热议问题