37

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

15 Answers 15

46

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; } 
Sign up to request clarification or add additional context in comments.

6 Comments

but it give result once screen get scrolled completely...is there any way to as start scrolling?
check my answer, it may not be the perfect solution but it's a start ;)
setOnPageChangeListener is deprecated now, use ViewPager.addOnPageChangeListener instead.
I tried all the solutions below and no one was working in my case. Good and simple solution. Nice job.
whats lastPage here? Is that supposed to be declared somewhere in this method.
|
43

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

10 Comments

how can i ctrl the left most click & the right most click?
Can you explain it better?
transformPage must @Override as ViewPager.PageTransformer has abstract method transformPage
@melvkim When it was first introduced in JDK 1.5, Override was only applicable to methods defined in a superclass, and not in a supertype. That is, it originally applied to overriding methods in a base class, but not to implementing methods defined in an interface. This was changed in JDK 7, and now Override can be applied to both. So the answer: we should use it, it's a good practice, but we don't have to. This code and Android example (tinyurl.com/cat4a6g) were written before JDK7. With IntelliJ when you override a method the "Add Override" by default its checked.
Note that transformPage() is called for multiple pages simultaneously, and some pages could end up having a different sign for its position value.
|
21
  1. This is my simple solution in the onPageScrolled() method of ViewPager.OnPageChangeListener:

enter image description here

2 Comments

Thank you, I think this solution is very smart and work great.
Great solution!
6

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

Comments

3

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

Comments

3

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 } } 

1 Comment

This is a very good solution, since it allows to monitor slide direction at any moment. Another solution stackoverflow.com/a/34356483/231590 monitors scroll direction during a single slide.
2

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.

Comments

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

Comments

1

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 { } } 

Comments

1

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

Comments

1

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

2 Comments

Code-only answers are discouraged on Stack Overflow because they don't explain how it solves the problem. Please edit your answer to explain how it solves the question and how it improves on the long-time and upvoted answers this question has, so that it is useful to users with similar issues.
Apologies - added some short description
0
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; } } }); 

Comments

0

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 } } 

Comments

0

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

Comments

-1
pager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { if(position == pager.getCurrentItem()){ // Move Right } else{ // Move Left } } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.