Nguyen  Minh Binh
Nguyen Minh Binh

Reputation: 24423

How to know viewpager is scroll left or right?

I am using ViewPager (support library). I want to know every time the ViewPager change the visible page, it is scrolling left or right.

Please give me a solution. Any recommend is welcome also.

Thanks

Upvotes: 36

Views: 43823

Answers (15)

Michael P
Michael P

Reputation: 245

Here's a way you can know the scroll direction while it's happening. All you have to do is set an OnPageChangeCallback() on the ViewPager. You save the current page of the ViewPager in OnPageSelected() and compare it to the position parameter of OnPageScrolled(). If the current page is less than or equal to the position, you are scrolling to the right, if not, you are scrolling to the left.

var currentPage = 0
viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
    override fun onPageSelected(position: Int) {
        super.onPageSelected(position)
        currentPage = position
    }

    override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
        super.onPageScrolled(position, positionOffset, positionOffsetPixels)
        if (currentPage <= position) {
            // We are scrolling right
        } else {
            // We are scrolling left
        }
    }
})

Upvotes: 0

linker
linker

Reputation: 891

dab on this if your worried about position offset suddenly changing to 0 after taking a value > 0.9F

    private boolean LEFT_DAB; //left swipe
    private float offset; //current position offset
    private float take_off; //previous position offset
    private static final float quavo = 0.5F; //position offset threshold

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        super.onPageScrolled(position, positionOffset, positionOffsetPixels);

        offset = take_off > 0.9F ? take_off : positionOffset;
        take_off = positionOffset;

        if (offset > quavo) {
            LEFT_DAB = false;//RIGHT_SWIPE
        } else {
            LEFT_DAB = true;//LEFT_SWIPE
        }
    }

Upvotes: 0

Ladislav Havlik
Ladislav Havlik

Reputation: 31

Apologies - had to edit the answer as I found a bug. Here is improved solution:

The solution compares current page index with one previously selected (previousPageIndex)

newPageIndex represents the page which is about to be scrolled to.

Condition (positionOffset == 0) compares if the scroll finished

private int previousPageIndex = 0;
private int newPageIndex = -1;

private final int MOVE_DIRECTION_NONE = 0;
private final int MOVE_DIRECTION_LEFT = 1;
private final int MOVE_DIRECTION_RIGHT = 2;

private int moveDirection = MOVE_DIRECTION_NONE;


@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
    super.onPageScrolled(position, positionOffset, positionOffsetPixels);

    if (moveDirection == MOVE_DIRECTION_NONE) {
        if (previousPageIndex  == position){
            moveDirection = MOVE_DIRECTION_LEFT;
            if (newPageIndex == -1) newPageIndex = previousPageIndex + 1;
        }  else {
            moveDirection = MOVE_DIRECTION_RIGHT;
            if (newPageIndex == -1) newPageIndex = previousPageIndex - 1;
        }
    }

    if (positionOffset == 0) {
        System.out.println("Reseting");
        previousPageIndex = position;
        moveDirection = MOVE_DIRECTION_NONE;
        newPageIndex = -1;
    }

    switch (moveDirection) {
        case MOVE_DIRECTION_LEFT:
            if (onPageChangingHandler != null) onPageChangingHandler.pageChanging(previousPageIndex, newPageIndex, positionOffset);
            System.out.println("Sliding Left | Previous index: " + previousPageIndex + " | New Index: " + newPageIndex + " | offset: " + positionOffset  + " | Position: " + position);
            break;
        case MOVE_DIRECTION_RIGHT:
            if (onPageChangingHandler != null) onPageChangingHandler.pageChanging(newPageIndex, previousPageIndex, positionOffset);
            System.out.println("Sliding Right | Previous index: " + previousPageIndex + " | New Index: " + newPageIndex + " | offset: " + positionOffset + " | Position: " + position);
            break;
        case MOVE_DIRECTION_NONE:
            System.out.println("Moving NONE");
            break;
    }
}

Upvotes: 1

Mohsin Naeem
Mohsin Naeem

Reputation: 12642

set setOnPageChangeListener to your ViewPager

keep a variable global as

private int lastPosition = 0;

and in

@Override
public void onPageSelected(int arg0) {
    if (lastPosition > position) {
         System.out.println("Left");
      }else if (lastPosition < position) {
         System.out.println("Right");
      }
      lastPosition = position;
}

Upvotes: 45

JayJoshi
JayJoshi

Reputation: 81

We can also do this using a Custom Viewpager, which can contain swipeLeft() and swipeRight() methods and its onTouchEvent(MotionEvent event) method can contain ACTION_MOVE and ACTION_CANCEL case.

// This can be the code if helpful.

public class SwiperViewPager extends ViewPager {

    SwiperListener mSwiperListener;
    private float downX;
    private float downY;
    private boolean isTouchCaptured;
    private float upX1;
    private float upY1;
    private float upX2;
    private float upY2;

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

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

    private float x1, x2;
    static final int min_distance = 20;

    boolean eventSent = false;

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_MOVE: {
                downX = event.getX();
                downY = event.getY();

                if (!isTouchCaptured) {
                    upX1 = event.getX();
                    upY1 = event.getY();
                    isTouchCaptured = true;
                } else {
                    upX2 = event.getX();
                    upY2 = event.getY();
                    float deltaX = upX1 - upX2;
                    float deltaY = upY1 - upY2;
                    //HORIZONTAL SCROLL
                    if (Math.abs(deltaX) > Math.abs(deltaY)) {
                        if (Math.abs(deltaX) > min_distance) {
                            // left or right
                            if (deltaX < 0) {
                                if(!eventSent && mSwiperListener!=null){
                                    mSwiperListener.onLeftSwipe();
                                    eventSent = true;
                                }
                            }
                            if (deltaX > 0) {
                                if(!eventSent && mSwiperListener!=null){
                                    if(mSwiperListener.onRightSwipe()){
                                        eventSent = true;
                                        return false;
                                    }
                                }
                            }
                        } else {
                            //not long enough swipe...
                        }
                    }
                    //VERTICAL SCROLL
                    else {
                        if (Math.abs(deltaY) > min_distance) {
                            // top or down
                            if (deltaY < 0) {

                            }
                            if (deltaY > 0) {

                            }
                        } else {
                            //not long enough swipe...
                        }
                    }
                }
            }
            break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:{
                isTouchCaptured = false;
                eventSent = false;
            }

        }
        return super.onTouchEvent(event);
    }

    public void setmSwiperListener(SwiperListener mSwiperListener) {
        this.mSwiperListener = mSwiperListener;
    }

    public static interface SwiperListener {
        public boolean onLeftSwipe();

        public boolean onRightSwipe();
    }

}

Upvotes: 1

Alexander Popov
Alexander Popov

Reputation: 188

private float sumPositionAndPositionOffset;

@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
    boolean isSwipeToLeft = position + positionOffset > sumPositionAndPositionOffset;
    sumPositionAndPositionOffset = position + positionOffset;   
}

Upvotes: 2

Kenneth Dixon
Kenneth Dixon

Reputation: 104

Same solution as GuilhE with a minor fix to avoid getting false positives when paging left (swiping right) on the first page(no more pages to the left) in the ViewPager. It simply does an additional check to see if the swipe has actually moved at all.

new ViewPager.OnPageChangeListener() {

  private static final float thresholdOffset = 0.5f;
  private static final int thresholdOffsetPixels = 1;
  private boolean scrollStarted, checkDirection;

  @Override
  public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
    if (checkDirection) {
      if (thresholdOffset > positionOffset && positionOffsetPixels > thresholdOffsetPixels) {
        Log.i(C.TAG, "going left");
      } else {
        Log.i(C.TAG, "going right");
      }
    checkDirection = false;
  }
}

  @Override
  public void onPageSelected(int position) {}

  @Override
  public void onPageScrollStateChanged(int state) {
    if (!scrollStarted && state == ViewPager.SCROLL_STATE_DRAGGING) {
      scrollStarted = true;
      checkDirection = true;
    } else {
      scrollStarted = false;
    }
  }
 });

Upvotes: 6

huu duy
huu duy

Reputation: 2059

  1. This is my simple solution in the onPageScrolled() method of ViewPager.OnPageChangeListener:

enter image description here

Upvotes: 21

Muzaffer
Muzaffer

Reputation: 1457

I solved the issue with this implementation. Hope it helps.

public static final float EPSILON= 0.001f;

@Override
public void onPageScrolled(final int position, final float positionOffset, final int positionOffsetPixels) {

    // initial position (positionOffset == 0)
    if (positionOffset < EPSILON) {
        mIsRight = positionOffset < 0.5;
        return;
    }

    // code here
    if (mIsRight) {
    } else {
    }
}

Upvotes: 1

KingWu
KingWu

Reputation: 390

pager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            if(position  == pager.getCurrentItem()){
                // Move Right
            }
            else{
                // Move Left
            }

        }

Upvotes: -1

GuilhE
GuilhE

Reputation: 11861

It's not a perfect solution but here's a way to check the swipe direction when you start swiping:

new ViewPager.OnPageChangeListener() {

            private static final float thresholdOffset = 0.5f;
            private boolean scrollStarted, checkDirection;

            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                if (checkDirection) {
                    if (thresholdOffset > positionOffset) {
                        Log.i(C.TAG, "going left");
                    } else {
                        Log.i(C.TAG, "going right");
                    }
                    checkDirection = false;
                }
            }

            @Override
            public void onPageSelected(int position) {}

            @Override
            public void onPageScrollStateChanged(int state) {
                if (!scrollStarted && state == ViewPager.SCROLL_STATE_DRAGGING) {
                    scrollStarted = true;
                    checkDirection = true;
                } else {
                    scrollStarted = false;
                }
            }
        });


EDIT: there's a more elegant approach that involves using a ViewPager.PageTransformer and checking it's position intervals:

...
myViewPager.setPageTransformer(true, new PageTransformer());
...

public class PageTransformer implements ViewPager.PageTransformer {
    public void transformPage(View view, float position) {

        if (position < -1) { 
            // [-00,-1): the page is way off-screen to the left.
        } else if (position <= 1) { 
            // [-1,1]: the page is "centered"
        } else { 
            // (1,+00]: the page is way off-screen to the right.           
        }
    }
}

You can learn more from: Using ViewPager for Screen Slides

Upvotes: 43

ultra.deep
ultra.deep

Reputation: 1809

use that

@Override
public void onPageSelected( int position )
{
    mCurrentFragmentPosition = position;
}
@Override
public void onPageScrolled( int position, float positionOffset, int positionOffsetPixels )
{
    boolean isGoingToRightPage = position == mCurrentFragmentPosition;
    if(isGoingToRightPage)
    {
        // user is going to the right page
    }
    else
    {
        // user is going to the left page
    }
}

Upvotes: 3

Mukesh Kumar
Mukesh Kumar

Reputation: 1

viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {

        private int mCurrentSelectedScreen;
        private int mNextSelectedScreen;
        private static final float thresholdOffset = 0.5f;
        private boolean scrollStarted=true, checkDirection=false;
        ArrayList<Integer> comp_ary=new ArrayList<Integer>();

        @Override
        public void onPageSelected(int arg0) {
        }

        @Override
        public void onPageScrolled(int position, float positionOffset,
                int positionOffsetPixels) {

        //Log.e("positionOffsetPixels : "+positionOffsetPixels, "positionOffset : "+positionOffset);
        comp_ary.add(positionOffsetPixels);
             if (checkDirection) {
                    if (comp_ary.get(2) < comp_ary.get(comp_ary.size()-1)) {

                        Log.e("going left", "going left");
                    } else
                        if (comp_ary.get(2) > comp_ary.get(comp_ary.size()-1))
                    {

                        Log.e("going right", "going right");
                    }
                    checkDirection = false;
                    comp_ary=new ArrayList<Integer>();
                }
        }

        @Override
        public void onPageScrollStateChanged(int arg0) {




            if (!scrollStarted && arg0 == ViewPager.SCROLL_STATE_SETTLING) {
                scrollStarted = true;
                checkDirection = true;
            } else {
                scrollStarted = false;
            }


        }
    });

Upvotes: 0

Gagandeep Singh
Gagandeep Singh

Reputation: 17453

You can keep class member variable to save last visited page

private int mLastVisitedPageIndex = 0;

Then use following function to check direction

@Override
public void onPageSelected(int i) {
    boolean isMovingForward = mLastVisitedPageIndex < i?true:false;
    //Use isMovingForward variable anywhere now
    mLastVisitedPageIndex = i;
}

Upvotes: 3

Karakuri
Karakuri

Reputation: 38585

Use the ViewPager.OnPageChangeListener interface. You can use the position argument passed to onPageSelected and compare it to the previous value to figure out which way the ViewPager was scrolled.

Upvotes: 2

Related Questions