viewpager stop disable cancel android android-viewpager

android - stop - ¿Cómo deshabilitar la paginación al deslizar con el dedo en ViewPager pero aún así se puede deslizar programáticamente?



disable swipe viewpager (17)

Es mejor declararlo con estilo, para que pueda 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 tus valores / attr.xml:

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

para que puedas usarlo en tu 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.

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


Escribí un CustomViewPager con un control de deslizamiento:

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 establece canScroll en true , este ViewPager puede ViewPager con el dedo, por el contrario, false .

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



La extensión más general de ViewPager sería crear un método SetPagingEnabled para que podamos habilitar y deshabilitar la paginación sobre la marcha. Para habilitar / deshabilitar el deslizamiento, simplemente anule dos métodos: onTouchEvent y onInterceptTouchEvent . Ambos devolverán "falso" si la paginación fue 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; } }

Luego seleccione esto en lugar del viewpager incorporado en XML

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

Solo necesita llamar al método setPagingEnabled con false y los usuarios no podrán deslizarse para 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; } });


Necesitaba deshabilitar el deslizamiento en una página específica, y darle una buena animación de banda elástica, así es como:

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


Necesitas subclasificar ViewPager. onTouchEvent tiene muchas cosas buenas que no quieres cambiar, como permitir que las vistas de los niños reciban toques. onInterceptTouchEvent es lo que quieres 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. */

Aquí hay una solución completa:

Primero, agregue esta clase a su 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 usar esta clase en lugar del ViewPager normal, que probablemente haya especificado como android.support.v4.view.ViewPager. En su archivo de diseño, querrá 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 un LinearLayout y está destinado a ocupar toda la pantalla, por lo que layout_weight es 1 y layout_height es 0dp.

Y setMyScroller (); el metodo es para una transicion suave


Ninguno de los códigos anteriores funciona correctamente. Lo he intentado.

<HorizontalScrollView android:id="@+id/horizontalScrollView" android:layout_width="match_parent" android:layout_height="match_parent" android:fillViewport="true"> <android.support.v4.view.ViewPager android:id="@+id/pager" android:layout_width="match_parent" android:layout_height="match_parent" /> </HorizontalScrollView>


Otra solución fácil para desactivar el deslizamiento 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; }


Para desactivar el deslizamiento

mViewPager.beginFakeDrag();

Para habilitar el deslizamiento

mViewPager.endFakeDrag();


Sé que es muy tarde para publicar esto, pero aquí hay un pequeño truco para lograr tu 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>

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

Sea un poco creativo con los diseños, sus ubicaciones y su comportamiento, y aprenderá a encontrar la manera de hacer absolutamente todo lo que imagina :)

¡Buena suerte!


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

Elegí nombrar el atributo " ScrollEnabled ". Porque iOS solo usa el mismo nombre de excat. Por lo tanto, tiene el mismo nombre 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://.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>


Si se está extendiendo desde ViewPager, también debe anular executeKeyEvent como se indicó anteriormente en @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:


Una solución simple se describe aquí: Implementar un ImageView con zoom extendiendo el ViewPager predeterminado en Phimpme Android (y muestra de Github - PhotoView ):

public class CustomViewPager extends ViewPager { public CustomViewPager(Context context) { super(context); } public CustomViewPager(Context context, AttributeSet attrs) { super(context,attrs); } @Override public boolean onInterceptTouchEvent(MotionEvent event) { try { return super.onInterceptTouchEvent(event); } catch (IllegalArgumentException e) { return false; } } }


Utilicé esta clase con éxito. Se requiere anular el executeKeyEvent para evitar el deslizamiento usando flechas en algunos dispositivos o para accesibilidad:

import android.content.Context; import android.support.v4.view.ViewPager; import android.util.AttributeSet; import android.view.KeyEvent; import android.view.MotionEvent; public class ViewPagerNoSwipe extends ViewPager { /** * Is swipe enabled */ private boolean enabled; public ViewPagerNoSwipe(Context context, AttributeSet attrs) { super(context, attrs); this.enabled = false; // By default swiping is disabled } @Override public boolean onTouchEvent(MotionEvent event) { return this.enabled ? super.onTouchEvent(event) : false; } @Override public boolean onInterceptTouchEvent(MotionEvent event) { return this.enabled ? super.onInterceptTouchEvent(event) : false; } @Override public boolean executeKeyEvent(KeyEvent event) { return this.enabled ? super.executeKeyEvent(event) : false; } public void setSwipeEnabled(boolean enabled) { this.enabled = enabled; } }

Y en el xml llámalo así:

<package.path.ViewPagerNoSwipe android:layout_width="match_parent" android:layout_height="match_parent" />


onTouchEvent solo onTouchEvent y onInterceptTouchEvent no es suficiente en caso de que tenga ViewPager dentro de otro ViewPager. Child ViewPager robaría eventos táctiles de desplazamiento horizontal de ViewPager principal a menos que se coloque en su primera / última página.

Para que esta configuración funcione correctamente, también debe anular 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); } }


This worked for me viewPager.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (viewPager.getCurrentItem() == 0) { viewPager.setCurrentItem(-1, false); return true; } else if (viewPager.getCurrentItem() == 1) { viewPager.setCurrentItem(1, false); return true; } else if (viewPager.getCurrentItem() == 2) { viewPager.setCurrentItem(2, false); return true; } return true; } });