¿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?
- Diferencia entre FragmentPagerAdapter y FragmentStatePagerAdapter
- Problema extraño que refresca ViewPager con nuevo contenido:
- ViewPager con múltiples PageTransformer (PageTransformers en Runtime)
- Error al cargar fragmentos cuando las pestañas + viewpager dentro de scrollview?
- Nesting Android ViewPager, Swiping ListItems dentro de un ListView horizontalmente
- GetTag () devuelve siempre null cuando se llama en fragmento
- Android ViewPager llama manualmente a PageTransformer transformPage
- Actividad de inicio de Fragmento causa NullPointerException
- Cómo evitar que viewpager inicialice la vista siguiente de forma predeterminada en android?
- ViewPager parece reenable clipChildren al desplazarse si se configura PageTransformer
- Manejo de PagerTitleStrip haga clic en compatibilidad Fragment-based ViewPager
- FragmentPagerAdapter y FragmentStatePagerAdapter
- Actualizando viewpager con fragmentos en un nuevo orden
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:
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>
- Diferencia entre el relleno y el margen de una vista
- Botón estándar de Android con un color diferente