Reputation: 24423
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
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
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
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
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
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
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
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
Reputation: 2059
Upvotes: 21
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
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
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
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
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
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
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