¿Cómo deshabilitar la paginación mediante el desplazamiento con el dedo en ViewPager, pero todavía ser capaz de deslizar de forma programática?

Tengo ViewPager y debajo de él tengo 10 botones. Al hacer clic en el botón, por ejemplo # 4, el paginador va inmediatamente a la página # 4 por mPager.setCurrentItem(3); . Pero, quiero desactivar la paginación deslizando con el dedo horizontalmente. Por lo tanto, la paginación se hace SOLAMENTE haciendo clic en los botones. Entonces, ¿cómo puedo desactivar el deslizamiento con el dedo?

Necesitas subclasificar ViewPager. OnTouchEvent tiene muchas cosas buenas en las que no quieres cambiar, como permitir que las vistas de los niños obtengan toques. OnInterceptTouchEvent es lo que desea cambiar. Si miras el código de ViewPager, verás el comentario:

  /* * This method JUST determines whether we want to intercept the motion. * If we return true, onMotionEvent will be called and we do the actual * scrolling there. */ 

He aquí una solución completa:

Primero, agrega esta clase a tu carpeta src:

 import android.content.Context; import android.support.v4.view.ViewPager; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.animation.DecelerateInterpolator; import android.widget.Scroller; import java.lang.reflect.Field; public class NonSwipeableViewPager extends ViewPager { public NonSwipeableViewPager(Context context) { super(context); setMyScroller(); } public NonSwipeableViewPager(Context context, AttributeSet attrs) { super(context, attrs); setMyScroller(); } @Override public boolean onInterceptTouchEvent(MotionEvent event) { // Never allow swiping to switch between pages return false; } @Override public boolean onTouchEvent(MotionEvent event) { // Never allow swiping to switch between pages return false; } //down one is added for smooth scrolling private void setMyScroller() { try { Class<?> viewpager = ViewPager.class; Field scroller = viewpager.getDeclaredField("mScroller"); scroller.setAccessible(true); scroller.set(this, new MyScroller(getContext())); } catch (Exception e) { e.printStackTrace(); } } public class MyScroller extends Scroller { public MyScroller(Context context) { super(context, new DecelerateInterpolator()); } @Override public void startScroll(int startX, int startY, int dx, int dy, int duration) { super.startScroll(startX, startY, dx, dy, 350 /*1 secs*/); } } } 

A continuación, asegúrese de utilizar esta clase en lugar del ViewPager normal, que probablemente ha especificado como android.support.v4.view.ViewPager. En tu archivo de diseño, deberás especificarlo con algo como:

 <com.yourcompany.NonSwipeableViewPager android:id="@+id/view_pager" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" /> 

Este ejemplo en particular está en LinearLayout y está destinado a ocupar toda la pantalla, por lo que layout_weight es 1 y layout_height es 0dp.

Y setMyScroller (); Método es para una transición suave

La extensión más general de ViewPager sería crear un método SetPagingEnabled para que podamos activar y desactivar la paginación sobre la marcha. Para habilitar / deshabilitar el swiping, sólo dos métodos onTouchEvent : onTouchEvent y onInterceptTouchEvent . Ambos devolverán "false" si la paginación está deshabilitada.

 public class CustomViewPager extends ViewPager { private boolean enabled; public CustomViewPager(Context context, AttributeSet attrs) { super(context, attrs); this.enabled = true; } @Override public boolean onTouchEvent(MotionEvent event) { if (this.enabled) { return super.onTouchEvent(event); } return false; } @Override public boolean onInterceptTouchEvent(MotionEvent event) { if (this.enabled) { return super.onInterceptTouchEvent(event); } return false; } public void setPagingEnabled(boolean enabled) { this.enabled = enabled; } } 

A continuación, seleccione este en lugar del built-in viewpager en XML

 <mypackage.CustomViewPager android:id="@+id/myViewPager" android:layout_height="match_parent" android:layout_width="match_parent" /> 

Sólo tiene que llamar al método setPagingEnabled con false y los usuarios no podrán pasar a paginar.

La forma más sencilla es setOnTouchListener y devolver true para ViewPager .

 mPager.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { return true; } }); 

Mejor para declararlo estilo, por lo que puede cambiar su propiedad de xml:

 private boolean swipeable; public MyViewPager(Context context, AttributeSet attrs) { super(context, attrs); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyViewPager); try { swipeable = a.getBoolean(R.styleable.MyViewPager_swipeable, true); } finally { a.recycle(); } } @Override public boolean onInterceptTouchEvent(MotionEvent event) { return swipeable ? super.onInterceptTouchEvent(event) : false; } @Override public boolean onTouchEvent(MotionEvent event) { return swipeable ? super.onTouchEvent(event) : false; } 

Y en sus valores / attr.xml:

 <declare-styleable name="MyViewPager"> <attr name="swipeable" format="boolean" /> </declare-styleable> 

Para que pueda usarlo en su layout xml:

 <mypackage.MyViewPager xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/viewPager" android:layout_width="wrap_content" android:layout_height="wrap_content" app:swipeable="false" /> 

Por supuesto, todavía puede tener una propiedad get / set.

La onTouchEvent sólo onTouchEvent y onInterceptTouchEvent no es suficiente en caso de que tenga ViewPager dentro de otro ViewPager. Child ViewPager activaría eventos de desplazamiento de desplazamiento horizontal desde ViewPager padre a menos que esté situado en su primera / última página.

Para que esta configuración funcione correctamente, debe anular también el método canScrollHorizontally .

Vea la implementación de LockableViewPager continuación.

 public class LockableViewPager extends ViewPager { private boolean swipeLocked; public LockableViewPager(Context context) { super(context); } public LockableViewPager(Context context, AttributeSet attrs) { super(context, attrs); } public boolean getSwipeLocked() { return swipeLocked; } public void setSwipeLocked(boolean swipeLocked) { this.swipeLocked = swipeLocked; } @Override public boolean onTouchEvent(MotionEvent event) { return !swipeLocked && super.onTouchEvent(event); } @Override public boolean onInterceptTouchEvent(MotionEvent event) { return !swipeLocked && super.onInterceptTouchEvent(event); } @Override public boolean canScrollHorizontally(int direction) { return !swipeLocked && super.canScrollHorizontally(direction); } } 

Para inhabilitar el golpe

 mViewPager.beginFakeDrag(); 

Para habilitar el desplazamiento

 mViewPager.endFakeDrag(); 

Necesitaba inhabilitar el barrido en una página específica, y darle una animación agradable de la goma-venda, aquí es cómo:

  mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { if (position == MANDATORY_PAGE_LOCATION && positionOffset > 0.5) { mViewPager.setCurrentItem(MANDATORY_PAGE_LOCATION, true); } } 

Si se está extendiendo desde ViewPager, también debe sobrescribir executeKeyEvent como se indica anteriormente por @araks

 @Override public boolean executeKeyEvent(KeyEvent event) { return isPagingEnabled ? super.executeKeyEvent(event) : false; } 

Debido a que algunos dispositivos como el Galaxy Tab 4 10 'muestran estos botones donde la mayoría de los dispositivos nunca los muestran:

Botones del teclado

Sé que es muy tarde para publicar esto, pero aquí hay un pequeño hack para lograr su resultado;)

Simplemente agregue una vista ficticia debajo de su viewpager:

 <android.support.v4.view.ViewPager android:layout_width="match_parent" android:layout_height="match_parent"> </android.support.v4.view.ViewPager> <RelativeLayout android:id="@+id/dummyView" android:layout_width="match_parent" android:layout_height="match_parent"> </RelativeLayout> 

A continuación, agregue un OnClickListener a su RelativeLayout .

 dummyView = (RelativeLayout) findViewById(R.id.dummyView); dummyView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //Just leave this empty } }); 

Obtener un poco creativo con los diseños, sus ubicaciones y su comportamiento y usted aprenderá a encontrar una manera de hacer absolutamente cualquier cosa que te imaginas 🙂

¡Buena suerte!

Escribí un CustomViewPager con un control CustomViewPager :

 public class ScrollableViewPager extends ViewPager { private boolean canScroll = true; public ScrollableViewPager(Context context) { super(context); } public ScrollableViewPager(Context context, AttributeSet attrs) { super(context, attrs); } public void setCanScroll(boolean canScroll) { this.canScroll = canScroll; } @Override public boolean onTouchEvent(MotionEvent ev) { return canScroll && super.onTouchEvent(ev); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { return canScroll && super.onInterceptTouchEvent(ev); } } 

Si ajusta canScroll a true , este ViewPager puede ser ViewPager con finger, false por el contrario.

Yo uso esto en mi proyecto, y funciona muy bien hasta ahora.

Trate de sobreescribir y devolver true desde onInterceptTouchEvent () y / o onTouchEvent () , que consumirá eventos táctiles en el paginador.

Otra solución fácil para inhabilitar el desplazamiento en una página específica (en este ejemplo, página 2):

 int PAGE = 2; viewPager.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (viewPager.getCurrentItem() == PAGE) { viewPager.setCurrentItem(PAGE-1, false); viewPager.setCurrentItem(PAGE, false); return true; } return false; } 

Si quieres implementar lo mismo para Android en Xamarin, aquí hay una traducción a C #

Elegí nombrar el atributo " ScrollEnabled ". Debido a que iOS sólo utiliza el excat mismo nombre. Por lo tanto, tiene la igualdad de nombres en ambas plataformas, lo hace más fácil para los desarrolladores.

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using Android.App; using Android.Content; using Android.OS; using Android.Runtime; using Android.Views; using Android.Widget; using Android.Support.V4.View; using Android.Util; namespace YourNameSpace.ViewPackage { // Need to disable swiping for ViewPager, if user performs Pre DSA and the dsa is not completed yet // http://stackoverflow.com/questions/9650265/how-do-disable-paging-by-swiping-with-finger-in-viewpager-but-still-be-able-to-s public class CustomViewPager: ViewPager { public bool ScrollEnabled; public CustomViewPager(Context context, IAttributeSet attrs) : base(context, attrs) { this.ScrollEnabled = true; } public override bool OnTouchEvent(MotionEvent e) { if (this.ScrollEnabled) { return base.OnTouchEvent(e); } return false; } public override bool OnInterceptTouchEvent(MotionEvent e) { if (this.ScrollEnabled) { return base.OnInterceptTouchEvent(e); } return false; } // For ViewPager inside another ViewPager public override bool CanScrollHorizontally(int direction) { return this.ScrollEnabled && base.CanScrollHorizontally(direction); } // Some devices like the Galaxy Tab 4 10' show swipe buttons where most devices never show them // So, you could still swipe through the ViewPager with your keyboard keys public override bool ExecuteKeyEvent(KeyEvent evt) { return this.ScrollEnabled ? base.ExecuteKeyEvent(evt) : false; } } } 

En el archivo .axml:

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <YourNameSpace.ViewPackage.CustomViewPager android:id="@+id/pager" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@android:color/white" android:layout_alignParentTop="true" /> </LinearLayout> 
  • ¿Cómo saber qué fragmento está seleccionado actualmente en un ViewPager?
  • ViewPager en ScrollView
  • ¿Cómo probar si una vista fragmentada es visible para el usuario?
  • Android: desplazamiento horizontal de varios elementos visibles
  • Android cómo detener la actualización Fragmentos en el cambio de ficha
  • Deshabilitar los gestos en PagerAdapter / ViewPager
  • ViewPager con múltiples instancias de fragmentos de la misma clase
  • Vista web de Android: evita que los gestos táctiles se pasen a la vista principal de los padres
  • Retener el estado de fragmentos de viewpager android
  • Anfitrión de múltiples fragmentos en viewpager
  • ListFragment no vuelve a mostrar datos al llamar desde FragmentStatePagerAdapter
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.