Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to disable ViewPager from swiping in one direction

I want to allow the user swipe in a ViewPager only from right to left. So once he passed a page he can't come back to it. How can this be done?

I tried this solution:

public class CustomViewPager extends ViewPager {  float lastX = 0;  boolean lockScroll = false;  public CustomViewPager(Context context, AttributeSet attrs) {     super(context, attrs); }  public CustomViewPager(Context context) {     super(context); }  @Override public boolean onTouchEvent(MotionEvent ev) {      switch (ev.getAction()) {     case MotionEvent.ACTION_DOWN:         lastX = ev.getX();         lockScroll = false;         return super.onTouchEvent(ev);     case MotionEvent.ACTION_MOVE:          if (lastX > ev.getX()) {             lockScroll = false;         } else {             lockScroll = true;         }          lastX = ev.getX();         break;     }      lastX = ev.getX();      if(lockScroll) {         return false;     } else {         return super.onTouchEvent(ev);     } } } 

But it still allows me to poorly swipe in the other direction.

like image 282
Emil Adz Avatar asked Oct 26 '13 03:10

Emil Adz


People also ask

How do I stop ViewPager swiping?

To enable / disable the swiping, just overide two methods: onTouchEvent and onInterceptTouchEvent . Both will return "false" if the paging was disabled. You just need to call the setPagingEnabled method with false and users won't be able to swipe to paginate.

How do I turn off swipe in ViewPager Kotlin?

There is no built in way to disable swiping between pages of a ViewPager, what's required is an extension of ViewPager that overrides onTouchEvent and onInterceptTouchEvent to prevent the swiping action. To make it more generalised we can add a method setSwipePagingEnabled to enable/disable swiping between pages.

Is ViewPager deprecated?

This function is deprecated.


2 Answers

There is one more event you miss: onInterceptTouchEvent. It`s must contain the same logic as onTouchEvent.

My complete solution is based on this answer. It will allow you to enable/disable paging in any direction in any time you need.

1. Create enum

 public enum SwipeDirection {     ALL, LEFT, RIGHT, NONE ; } 

2.Extend ViewPager (in Java)

public class CustomViewPager extends ViewPager {      private float initialXValue;     private SwipeDirection direction;      public CustomViewPager(Context context, AttributeSet attrs) {         super(context, attrs);         this.direction = SwipeDirection.ALL;     }      @Override     public boolean onTouchEvent(MotionEvent event) {         if (this.isSwipeAllowed(event)) {             return super.onTouchEvent(event);         }          return false;     }      @Override     public boolean onInterceptTouchEvent(MotionEvent event) {         if (this.isSwipeAllowed(event)) {             return super.onInterceptTouchEvent(event);         }          return false;     }      private boolean isSwipeAllowed(MotionEvent event) {         if(this.direction == SwipeDirection.ALL) return true;          if(direction == SwipeDirection.NONE )//disable any swipe             return false;          if(event.getAction()==MotionEvent.ACTION_DOWN) {             initialXValue = event.getX();             return true;         }          if (event.action === MotionEvent.ACTION_MOVE) {             val diffX = event.x - initialXValue             if (diffX > 0 && direction === SwipeDirection.RIGHT) {                 // swipe from left to right detected                 return false             } else if (diffX < 0 && direction === SwipeDirection.LEFT) {                 // swipe from right to left detected                 return false             }         }          return true;     }      public void setAllowedSwipeDirection(SwipeDirection direction) {         this.direction = direction;     } } 

2.Extend ViewPager (in Kotlin)

enum class SwipeDirection {     ALL, LEFT, RIGHT, NONE }  class SingleDirectionViewPager @JvmOverloads constructor(     context: Context,     attrs: AttributeSet? ) : ViewPager(context, attrs) {      private var initialXValue = 0f     private var direction: SwipeDirection = SwipeDirection.ALL      override fun onTouchEvent(event: MotionEvent): Boolean =         if (isSwipeAllowed(event)) {             super.onTouchEvent(event)         } else {             false         }      override fun onInterceptTouchEvent(event: MotionEvent): Boolean =         if (isSwipeAllowed(event)) {             super.onInterceptTouchEvent(event)         } else {             false         }      private fun isSwipeAllowed(event: MotionEvent): Boolean {         if (direction == SwipeDirection.ALL) {             return true         }          if (direction == SwipeDirection.NONE) {             return false         }          if (event.action == MotionEvent.ACTION_DOWN) {             initialXValue = event.x             return true         }          if (event.action == MotionEvent.ACTION_MOVE) {             val diffX = event.x - initialXValue              if (diffX > 0 && direction === SwipeDirection.RIGHT) {                 // swipe from left to right detected                 return false             } else if (diffX < 0 && direction === SwipeDirection.LEFT) {                 // swipe from right to left detected                 return false             }         }          return true     }      fun setAllowedSwipeDirection(direction: SwipeDirection) {         this.direction = direction     } } 

3.Use your viewPager in a layout

 <package_name.customviewpager       android:id="@+id/customViewPager"       android:layout_height="match_parent"       android:layout_width="match_parent" /> 

4.Enable any swipe direction in code. Default is all (right and left)

mViewPager.setAllowedSwipeDirection(SwipeDirection.RIGHT); 
like image 177
andre719mv Avatar answered Oct 02 '22 11:10

andre719mv


package com.contacts_app.jamison.contacts__proprivacy4;  import android.content.Context; import android.content.res.Resources; import android.support.v4.view.ViewPager; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent;  public class ViewPager_Settings extends ViewPager { private final String TAG = ViewPager_Settings.class.getSimpleName(); public float startX;  public ViewPager_Settings(Context context, AttributeSet attrs) {     super(context, attrs); }   //////////////////////////////////////////////////////////////////////////////////////////////// public static int dpTOpx(double dp) {     return (int) (dp * Resources.getSystem().getDisplayMetrics().density); } public static int pxTOdp(double px) {     return (int) (px / Resources.getSystem().getDisplayMetrics().density); } ////////////////////////////////////////////////////////////////////////////////////////////////  /*****DispatchTouchEvent for the View Pager to intercept and block swipes Right*****/ @Override public boolean dispatchTouchEvent(MotionEvent ev) {     final int actionMasked = ev.getActionMasked() & MotionEvent.ACTION_MASK;     //int movement_limit = pxTOdp(50);     switch (actionMasked)     {         case (MotionEvent.ACTION_DOWN):         {             startX = ev.getX();             Log.i(TAG, "startX: " + startX);              /*Should always be this below*/             return super.dispatchTouchEvent(ev);         }         case (MotionEvent.ACTION_MOVE):         {             Log.i(TAG, "ev.getX() - startX:" + (ev.getX() - startX));              /*Switching directional changes would be a matter of flipping the  "<" sign in the line below.*/             if (ev.getX() - startX > 0)             {                 /*The result is that the ViewPager will not swipe from left*/                 ev.setAction(MotionEvent.ACTION_CANCEL);;             }              /*Should always be this below*/             super.dispatchTouchEvent(ev);         }         /**The ACTION_UP case statement is only needed if you don't want to pass down the touch event          * to buttons that may receive the click after the swipe is blocked.*/         /*case (MotionEvent.ACTION_UP):         {             //Log.i(TAG, "movement_limit: " + movement_limit);              //(-50) may need to be changed to something more broader in scope to accompany all screen densities             if ( (ev.getX() - startX) < (-50) )             {                 ev.setAction(MotionEvent.ACTION_CANCEL);             }              //Should always be this below             super.dispatchTouchEvent(ev);         }*/     }     /*Should always be this below*/     return super.dispatchTouchEvent(ev); }  ////////////////////////////////////////////////////////////////////////////////////////////////  }/*****END OF FILE*****/ 

Don't forget to change the line at the top to put the package name of your App. Also most, if not all, of the comments give insight into what the code is doing in case you decide you want to tinker with things.

like image 31
JamisonMan111 Avatar answered Oct 02 '22 11:10

JamisonMan111