Как отключить ViewPager от прокрутки в одном направлении

Я хочу разрешить пользователю ViewPager в ViewPager только справа налево. Поэтому, как только он прошел страницу, он не может вернуться к нему. Как это может быть сделано?

Я пробовал это решение:

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

Но это все еще позволяет мне плохо салфетки в другом направлении.

Solutions Collecting From Web of "Как отключить ViewPager от прокрутки в одном направлении"

Еще одно событие, которое вы пропустите: onInterceptTouchEvent. Он должен содержать ту же логику, что и onTouchEvent.

Мое полное решение основано на этом ответе. Это позволит вам включать / отключать пейджинг в любом направлении в любое удобное для вас время.

1. Создать перечисление

  public enum SwipeDirection { all, left, right, none ; } 

2.Extend ViewPager

 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.getAction()==MotionEvent.ACTION_MOVE) { try { float diffX = event.getX() - 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; } } catch (Exception exception) { exception.printStackTrace(); } } return true; } public void setAllowedSwipeDirection(SwipeDirection direction) { this.direction = direction; } 

3. Используйте свой viewPager в макете

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

4.Enable любое направление движения в коде. По умолчанию все (справа и слева)

 mViewPager.setAllowedSwipeDirection(SwipeDirection.right); 

Определите свой адаптер следующим образом:

 public class MyFragmentStatePagerAdapter extends FragmentStatePagerAdapter { private final int totalPages = 10; private int currentPage = 0; public MyFragmentStatePagerAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int position) { // Use whatever logic you want here to // to select a fragment based on // currentPage instead of position if (currentPage % 2 == 0) { return new Fragment1(); } else { return new Fragment2(); } } @Override public int getCount() { return currentPage == totalPages ? 1 : 2; } @Override public int getItemPosition(Object object){ return PagerAdapter.POSITION_NONE; } public void nextPage() { currentPage++; notifyDataSetChanged(); } } 

В фрагменте, использующем пейджер представления, сделайте это

 @Override public void onPageSelected(int arg0) { if (arg0 > 0) { pagerAdapter.nextPage(); pager.setCurrentItem(0, false); } } 

Попробуйте добавить (та же логика, что и в onTouchEvent)

 @Override public boolean onInterceptTouchEvent(MotionEvent arg0) { // allow/ not allow swiping to switch between pages return !lockScroll ; } 
 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*****/ 

Не забудьте изменить строку вверху, чтобы поместить имя пакета вашего приложения. Кроме того, большинство, если не все, комментариев дают представление о том, что делает код, в случае, если вы решите, что хотите возиться с вещами.