3

In my Android application, I am using a viewpager for image swiping. My requirement is, if a user swipes out of the first and last page, the activity should finish.

I have taken this example. But the method setOnSwipeOutListener is not called in my activity.

This is my custom view pager class:

public class CustomViewPager extends ViewPager {

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

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

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

} 

And below in my activity class I call setOnSwipeOutListener method on my custom viewpager class, but it does not get called.

myPager = (CustomViewPager) findViewById(R.id.home_pannels_pager);

.......

myPager.setOnSwipeOutListener(new OnSwipeOutListener() { // the method never called
    @Override
    public void onSwipeOutAtStart() {
        Log.e("swipe Out At Start ", "swipe out");
    }

    @Override
    public void onSwipeOutAtEnd() {
        Log.e("swipe Out At End ", "swipe end");
    }
});

myPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
    @Override
    public void onPageSelected(int po) {
        Log.e("positon", ""+po);
    }
});

Please help me to detect if the user has swiped beyond the first and last page to close this activity and how to call the method from code.

Community
  • 1
  • 1
M.A.Murali
  • 9,988
  • 36
  • 105
  • 182
  • "my requirement is if user swipe out of the first and last page the activity should be finished" -- IMHO, from a UX standpoint, this is dreadful. – CommonsWare Sep 17 '14 at 11:21
  • @CommonsWare Why would it be dreadful? When you use it in Onboarding, people swipe all the way down to the last page and on the last page they have to tap on a button or perform a different action. Instead, if they could swipe and end onboarding, wouldn't that be easier for them? – Gokhan Arik Sep 15 '16 at 21:08
  • 1
    @GokhanArik Because the user rarely can get back to the onboarding screen. With your proposal, they swipe, swipe, swipe, oops now they can't go back because they swiped one too many times. My comment was not with onboarding specifically, but I still would not do it even in your scenario. – CommonsWare Sep 15 '16 at 22:04
  • https://stackoverflow.com/a/76712000/19856629 this is worked – Kanan Jul 18 '23 at 10:58

4 Answers4

1

In my case, onInterceptTouchEvent does not work. I change the method with onTouchEvent and it is working. The original solution is from tjlian616

    @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);
}    
Community
  • 1
  • 1
Amad Yus
  • 2,856
  • 1
  • 24
  • 32
0

I have also used the code from this SO answer. Make sure you make the necessary changes to your activity class. Here's what I did...

I changed my activity so it implements CustomViewPager.OnSwipeOutListener.

In my activity, after my mPager = (CustomViewPager) findViewById(R.id.pager); line, I call mPager.setOnSwipeOutListener(this);

All you need to do then is override the onSwipeOutAtStart() and onSwipeOutAtEnd() methods in your activity.

Community
  • 1
  • 1
ban-geoengineering
  • 18,324
  • 27
  • 171
  • 253
0

I changed M.A.Murali's code:

public class CheckBoundsPager extends ViewPager {
    public CheckBoundsPager(Context context) {
        super(context);
    }

    public CheckBoundsPager(Context context, AttributeSet attrs) {
        super(context, attrs);

    }

    OnSwipeOutListener mListener;

    public void setOnSwipeOutListener(OnSwipeOutListener listener) {
        mListener = listener;
    }

    private float mStartDragX;
    private float mStartDragY;
    private float MIN_MOVE=50; //minimal movement in px - change it to you value


    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        float x = ev.getX();
        float y = ev.getY();
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN: {
                //here we set x and y on user start drag
                mStartDragX = x;
                mStartDragY = y;

                }
                break;
            case MotionEvent.ACTION_MOVE: {

                //most important to check if x drag is more than y
                float xDiff=Math.abs(mStartDragX-x);
                float yDiff=Math.abs(mStartDragY-y);

                //added condition if swipe y is less than x
                if (mStartDragX < x-MIN_MOVE && xDiff>yDiff &&  getCurrentItem() == 0) {
                    mListener.onSwipeOutAtStart();
                } else if (mStartDragX > x+MIN_MOVE
                        && xDiff>yDiff && getCurrentItem() == getAdapter().getCount() - 1) {
                    mListener.onSwipeOutAtEnd();
                }
                }
                break;
        }
        return super.onInterceptTouchEvent(ev);
    }

    public interface OnSwipeOutListener {

        public void onSwipeOutAtStart();

        public void onSwipeOutAtEnd();
    }
}

This solutions checks if we drag left or right and our drag's movement is in the x-axis. Remember to change MIN_MOVE.

buczek
  • 2,011
  • 7
  • 29
  • 40
Maciej Sikora
  • 19,374
  • 4
  • 49
  • 50
  • 2
    Welcome to StackOverflow. Instead of including all of the OP's question, please only show what needed to be changed. This will help future people with the same question better understand how you solved the problem. – buczek Jul 13 '16 at 13:31
-1

*You can achive this by impementing OnPageChangeListener

http://developer.android.com/reference/android/support/v4/view/ViewPager.OnPageChangeListener.html

myPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
    @Override
    public void onPageScrolled(int i, float v, int i2) {

    }
    @Override
    public void onPageSelected( int i) {
      if(i == 0 || i == list.size()- 1){
         finish();
      }
    }
    @Override
    public void onPageScrollStateChanged(int i) {
    }
});*
Sheetal Suryan
  • 495
  • 2
  • 7
  • 19