¿Cómo deshabilitar la paginación al deslizar con el dedo en ViewPager pero aún así poder deslizar mediante programación?

550

Tengo ViewPager y debajo tengo 10 botones. Al hacer clic en el botón, por ejemplo # 4, el localizador 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 búsqueda se realiza SOLO haciendo clic en los botones. Entonces, ¿cómo puedo desactivar el deslizamiento con el dedo?

teatral
fuente
¿Qué tal usar ViewFlipper en primer lugar? Le ahorrará mucho dolor de cabeza.
Alex Semeniuk

Respuestas:

885

Necesitas subclase ViewPager. onTouchEventtiene muchas cosas buenas que no desea cambiar, como permitir que las vistas de los niños obtengan toques. onInterceptTouchEventes lo que quieres cambiar. Si miras el código 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 srccarpeta:

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 de la regular ViewPager, que probablemente especificó 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 LinearLayoutay está destinado a ocupar toda la pantalla, razón por la cual layout_weightes 1 ylayout_height ay es 0dp.

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

louielouie
fuente
3
@louielouie En una nota al margen: ¿hay alguna razón en particular, por qué eligió la solución de 0dpaltura / 1peso sobre la match_parentaltura para lograr el efecto de pantalla completa? ¿Obtiene mejoras de rendimiento al hacerlo?
ubuntudroid
29
Esta respuesta no evita deslizar la página cuando se usan las teclas izquierda / derecha del teclado (pruébelo en el emulador). Puede que no sea un problema para dispositivos táctiles, pero con TV y computadoras portátiles puede ser uno.
Vincent Mimoun-Prat
8
@MarvinLabs @Thorbear La forma correcta de deshabilitar el desplazamiento de la página con el teclado es anular el executeKeyEvent(). Este es el método que luego llama allowScroll(). // Never allow swiping by keyboard LEFT, RIGHT, TAB and SHIFT+TAB keys @Override public boolean executeKeyEvent(KeyEvent event) { return false; }
araks
66
bueno, esto también deshabilita el desplazamiento vertical ... esto es malo, si estás usando vistas de lista.
maysi
55
Espero que Google haya podido proporcionar un método al que proporcionamos nuestro método de interfaz sobre cómo manejar los toques / deslizamientos porque creo que no dolería.
Neon Warge
466

La extensión más general de ViewPagersería crear un SetPagingEnabledmétodo para que podamos habilitar y deshabilitar la paginación sobre la marcha. Para habilitar / deshabilitar el deslizamiento, simplemente anule dos métodos: onTouchEventy onInterceptTouchEvent. Ambos devolverán "falso" si se deshabilitó la paginación.

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 visor incorporado en XML

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

Solo necesita llamar al setPagingEnabledmétodo falsey los usuarios no podrán deslizarse para paginar.

Rajul
fuente
3
Funciona perfectamente para una vista que tiene varias subvistas donde uno usa el desplazamiento horizontal (por ejemplo, gráfico AChartEngine). En mi fragmento, utilizo una devolución de llamada para mi actividad que le indica que apague o desactive la paginación dependiendo de si el usuario tocó (ACTION_MOVE) el gráfico o lo dejó (ACTION_CANCEL). ¡Muchas gracias!
maduran
32
Puede simplificar sus onTouchEventy onInterceptTouchEventmétodos conreturn enabled && super.onTouchEvent(event);
nbarraille
2
@nbarraille es solo cuestión de estilo. Puede usar cualquier estilo que le parezca más legible.
Rajul
77
También recomendaría cambiar el nombre del campo de "habilitado" a "swipePageChangeEnabled" o algo así. Un mes después de escribir el código, difícilmente recordará lo que significa "habilitado", especialmente cuando su clase se llama "CustomViewPager", donde no está claro cuál es la personalización. Eso también es una cuestión de estilo, pero el estilo es importante si no desea terminar con un proyecto no compatible, que es más fácil de reescribir por completo que arreglarlo.
bytefu
44
¿Dónde llamo a setPagingEnabled? ._.
Ntikki
107

La forma más simple es setOnTouchListenervolver y truepara ViewPager.

mPager.setOnTouchListener(new OnTouchListener()
    {           
        @Override
        public boolean onTouch(View v, MotionEvent event)
        {
            return true;
        }
    });
Wayne
fuente
53
No funciona a veces. Estoy usando un ViewPager con un FragmentPagerAdapter y varios Fragment. Después de configurar OnTouchListener en buscapersonas, si giro hacia la izquierda, la IU aún se moverá un poco hacia la izquierda.
Chris.Zou
16
Funciona cuando agrega pager.setCurrentItem(pager.getCurrentItem());antes de regresar true.
dng
1
funcionó para mí antes. No tengo idea de por qué ya no funciona bien.
Desarrollador de Android
Parece funcionar para mi. Para resolver algunos problemas de diseño que tengo public int getItemPosition(Object object) { return POSITION_NONE; }en mi adaptador, lo que obliga a la recreación de las páginas y tal vez también resuelva otros problemas.
R-Hold
66
Esta es una solución PARCIALMENTE de trabajo. Los golpes horizontales se manejan de alguna manera extraña. Probé esto con una vista de cuadrícula de arrastrar y soltar como parte de un ViewPager. Al arrastrar con esta solución, falla el arrastre de izquierda a derecha y de derecha a izquierda. Personalmente, considero que el enfoque de Rajul es el mejor.
Ton Snoei
58

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 sus valores / attr.xml:

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

para que pueda usarlo en su diseño 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, aún puede tener una propiedad get / set.

Pietro
fuente
58

Anulando solo onTouchEventyonInterceptTouchEvent no es suficiente en caso de que tenga ViewPager dentro de otro ViewPager. El ViewPager secundario robaría los eventos táctiles de desplazamiento horizontal del ViewPager primario a menos que se coloque en su primera / última página.

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

Ver LockableViewPagerimplementación a 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);
    }

}
sidon
fuente
3
Gracias, esto funciona muy bien en un ViewPager dentro de otro ViewPager.
Fernanda Bari
1
Esto funciona para mí, también para un ViewPager dentro de otro ViewPager. La solución correcta no funcionó para mí en ese caso.
Rafael Ruiz Muñoz
también detiene la animación cuando se usa en pestañas.
Rishabh Srivastava
Si lo deshabilito y supongo que quiero habilitarlo, ¿dónde puedo obtener el evento para llamar a setSwipeLocked (falso)?
Ravi Yadav
58

Ahora no necesitamos crear personalizados ViewPager

Un nuevo ViewPager2 nombre Ver disponible en Android

Soporte de orientación vertical

  • ViewPager2admite paginación vertical además de la paginación horizontal tradicional. Puede habilitar la paginación vertical para un ViewPager2elemento estableciendo su android:orientationatributo

Usando XML

<androidx.viewpager2.widget.ViewPager2
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/pager"
    android:orientation="vertical" />

Usando código

Para deshabilitar el deslizamiento en viewpager2uso

viewPager2.setUserInputEnabled(false);

Para habilitar el deslizamiento en viewpager2uso

viewPager2.setUserInputEnabled(true);

para más información revisa esto

ACTUALIZAR

Nilesh Rathod
fuente
3
Es genial, pero aún parece estar incompleto. Lo probé con 5 fragmentos diferentes y después de cambiar de página, uno de los fragmentos se perdió, es decir, la vista no se restauró ni se volvió a inflar
Toochka
@Toochka lamento escuchar que para mí está funcionando bien, puedes encontrar el código de trabajo de muestra desde aquí stackoverflow.com/a/54643817/7666442 si es posible, comparte tu código
Nilesh Rathod
1
Podría deshabilitar con éxito el deslizamiento en un ViewPager2 usando este método
voghDev
1
@voghDev feliz de escuchar eso
Nilesh Rathod
1
@PhaniRithvij favor marque esta respuesta stackoverflow.com/a/54643817/7666442 he añadido todos los detalles de cómo utilizar viewpager2conRecyclerView.Adapter
Nilesh Rathod
35

Si está extendiendo desde ViewPager, también debe anularexecuteKeyEvent como se indicó 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

Grasa
fuente
50
Samsung siempre está arruinando las cosas para los desarrolladores de Android.
toobsco42
2
@ toobsco42 Samsung no está solo en este caso. SwiftKey (aplicación de teclado popular) permite a los usuarios colocar flechas en sus teclados.
Sufian
1
Esta es también la solución si desea evitar que alguien que usa un teclado / trackerball localice su buscapersonas.
se22as
28

Para deshabilitar deslizar

mViewPager.beginFakeDrag();

Para habilitar deslizar

mViewPager.endFakeDrag();
KAMAL VERMA
fuente
22
No es una buena solución porque permite pequeñas porciones de movimiento, al menos en mi aplicación.
koras
Funciona bien para mi. ¿Cuáles son las desventajas en comparación con las otras soluciones proporcionadas?
userM1433372
13

Necesitaba deshabilitar el deslizamiento en una página específica y darle una buena animación de goma, 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);
            }
        }
Oded Breiner
fuente
Espera hasta que la siguiente página sea parcialmente visible. Se onPageSelectedejecutará un código para la siguiente página . Incluso la siguiente página cambiará. Entonces, este código no es necesario.
CoolMind
13

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

Simplemente agregue una vista ficticia debajo de su visor:

<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 OnClickListenera 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!

Dinuka Jay
fuente
Una forma más fácil es usar en setClickablelugar de setOnClickListener, si no necesita manejar el onClickevento.
Caos
¿No bloquearía esto también los toques dentro del visor?
Desarrollador de Android
Sí lo hará Es el comportamiento esperado requerido por OP @androiddeveloper
Dinuka Jay
@RickGrimesTheCoder No creo que hayas entendido mi pregunta. Me refiero a las vistas dentro de los fragmentos del visor. ¿Seguirán siendo tocables?
Desarrollador de Android
No, no lo serán, ya que el visor en sí tiene un escucha de clics. Esto solo es adecuado para instancias en las que no tiene elementos interactivos dentro de los fragmentos. Por ejemplo, un ViewPager de bienvenida que cambia dinámicamente sus fragmentos @androiddeveloper
Dinuka Jay
12

Escribí un CustomViewPagercon un control deslizante:

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 se establece canScrollque true, este ViewPagerpuede birlar con el dedo, falsepor el contrario.

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

L. Swifter
fuente
1
¿Qué sucede si tengo un botón dentro de ViewPager y deseo el clic? esta solución detiene todo lo que está debajo del visor para hacer clic ..
aimiliano
6

Usé esta clase con éxito. Se requiere anular el executeKeyEvent para evitar deslizar el dedo 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" />
madx
fuente
Funciona. Solo deslizar está deshabilitado y hacer clic en una pestaña está habilitado. AS advierte que el performClick()método no se anula.
CoolMind
5

En Kotlin, mi solución, combina las respuestas anteriores.

class CustomViewPager(context: Context, attrs: AttributeSet): ViewPager(context, attrs) {
    var swipeEnabled = false

    override fun onTouchEvent(ev: MotionEvent?): Boolean {
        return if (swipeEnabled) super.onTouchEvent(ev) else false
    }

    override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
        return if (swipeEnabled) super.onInterceptTouchEvent(ev) else false
    }

    override fun executeKeyEvent(event: KeyEvent): Boolean {
        return if (swipeEnabled) super.executeKeyEvent(event) else false
    }
}
Jeff Padgett
fuente
La anulación onInterceptTouchEvent()evitará que las vistas secundarias reciban información. En la mayoría de los casos, este no es el comportamiento previsto.
Alex Semeniuk
Pude interactuar con las vistas infantiles de cada fragmento. No estoy seguro de a qué te refieres.
Jeff Padgett
5

En kotlin, podemos resolver esto creando un widget personalizado que herede la clase ViewPager y agregando un valor de indicador para controlar el comportamiento de deslizamiento.

NoSwipePager.kt

class NoSwipePager(context: Context, attrs: AttributeSet) : ViewPager(context, attrs) {

    var pagingEnabled: Boolean = false

    override fun onTouchEvent(event: MotionEvent): Boolean {
        return if (this.pagingEnabled) {
            super.onTouchEvent(event)
        } else false
    }

    override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
        return if (this.pagingEnabled) {
            super.onInterceptTouchEvent(event)
        } else false
    }
}

En xml

<your.package.NoSwipePager
    android:id="@+id/view_pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_below="@id/tab_layout" />

Inhabilita el deslizamiento mediante programación. Si el kotlin-android-extensionscomplemento se aplica en build.gradle , el deslizamiento se puede desactivar escribiendo el siguiente código.

view_pager.pagingEnabled = false

De lo contrario, podemos desactivar el deslizamiento usando el código a continuación:

val viewPager : ViewPager = findViewById(R.id.view_pager)
viewPager.pagingEnabled = false
Sagar Chapagain
fuente
La anulación onInterceptTouchEvent()evitará que las vistas secundarias reciban información. En la mayoría de los casos, este no es el comportamiento previsto.
Alex Semeniuk
@AlexSemeniuk ¿Ha observado algún problema después de implementar esto? Había habilitado el deslizamiento en elementos de la vista de reciclador para algunas acciones y está funcionando bien. Entonces la implementación está funcionando bien en mi caso.
Sagar Chapagain
Sagar Chapagain: o por supuesto, lo hice. Cada una de mis páginas contiene una vista personalizada, que procesa toques de varias maneras (incluido desplazamiento, arrastre, toques simples y largos). No llamar a super.onInterceptTouchEvent(event)resultados en estas vistas que no reciben ninguna entrada (que es el propósito documentado del onInterceptTouchEventmétodo).
Alex Semeniuk
Si ese es el caso, debería usar un fragmento secundario y mantener el backstack.
Sagar Chapagain
¿Cómo es esto relevante para la pregunta actual? Los fragmentos se colocan dentro de algunos contenedores (que son Vistas ) y su propio diseño contiene Vistas . No importa qué contenido tenga dentro de ViewPager, todavía estoy lidiando con el hecho de que el onInterceptTouchEvent()método de anulación evita que (contenido) reciba entradas.
Alex Semeniuk
4

Intente anular y devolver true desde onInterceptTouchEvent () y / o onTouchEvent () , que consumirá eventos táctiles en el buscapersonas.

AdamK
fuente
1
¿No querría volver truepara implicar que se ha manejado el evento táctil?
edthethird
1

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;
}
Ofir
fuente
1
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;
                                         }
                                     });
Princewill Iroka
fuente
1

Si escribe una galería de imágenes con ImageViewsy ViewPager, que admite zoom y panorámica, vea una solución simple que se describe aquí: Implementar un ImageView con zoom extendiendo el ViewPager predeterminado en Phimpme Android (y muestra de Github - PhotoView ). Esta solución no funciona ViewPagersolo.

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;
        }
    }
}
CoolMind
fuente
1

Si está utilizando ViewPager2 solo tiene que usar:

viewpager.setUserInputEnabled(false);

De los documentos :

Habilita o deshabilita el desplazamiento iniciado por el usuario. Esto incluye entrada táctil (gestos de desplazamiento y lanzamiento) y entrada de accesibilidad. Desactivar la entrada del teclado aún no es compatible. Cuando el desplazamiento iniciado por el usuario está deshabilitado, los desplazamientos programáticos a través de setCurrentItem siguen funcionando. Por defecto, el desplazamiento iniciado por el usuario está habilitado.

Gracias a: https://stackoverflow.com/a/61685871/9026710

Tayyab Mazhar
fuente
0

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 un nombre igual en ambas plataformas, lo que facilita a 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 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>
Lepidopteron
fuente
0

Ninguno de los códigos anteriores funciona sin problemas. Intenté esto

<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>
Nandan Singh
fuente
0

aquí está mi implementación
que si desea deshabilitar la animación de deslizamiento, puede usar el deslizador de deslizamiento hacia la izquierda y hacia la derecha y aún así desea el desplazamiento con el dedo pero sin animación

ViewpagerMétodo 1-Override onInterceptTouchEventyonTouchEvent

2- crea el tuyo GestureDetector

3- detecta el gesto de deslizar y usa el setCurrentItem(item, false)

ViewPager

public class ViewPagerNoSwipe extends ViewPager {
    private final GestureDetector gestureDetector;
    private OnSwipeListener mOnSwipeListener;

    public void setOnSwipeListener(OnSwipeListener onSwipeListener) {
        mOnSwipeListener = onSwipeListener;
    }

    public ViewPagerNoSwipe(@NonNull Context context) {
        super(context);
        gestureDetector = new GestureDetector(context, new GestureListener());

    }

    public ViewPagerNoSwipe(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        gestureDetector = new GestureDetector(context, new GestureListener());


    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        return true;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        gestureDetector.onTouchEvent(ev);
        return false;
    }

    public class GestureListener extends GestureDetector.SimpleOnGestureListener {

        private static final int SWIPE_THRESHOLD = 100;
        private static final int SWIPE_VELOCITY_THRESHOLD = 100;

        @Override
        public boolean onDown(MotionEvent e) {
            return true;
        }

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            boolean result = false;
            try {
                float diffY = e2.getY() - e1.getY();
                float diffX = e2.getX() - e1.getX();
                if (Math.abs(diffX) > Math.abs(diffY)) {
                    if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                        if (diffX > 0) {
                            if(mOnSwipeListener!=null)
                            mOnSwipeListener.onSwipeRight();
                        } else {
                            if(mOnSwipeListener!=null)
                                mOnSwipeListener.onSwipeLeft();
                        }
                        result = true;
                    }
                } else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
                    if (diffY > 0) {
                        if(mOnSwipeListener!=null)
                            mOnSwipeListener.onSwipeBottom();
                    } else {
                        if(mOnSwipeListener!=null)
                            mOnSwipeListener.onSwipeTop();
                    }
                    result = true;
                }
            } catch (Exception exception) {
                exception.printStackTrace();
            }
            return result;
        }
    }

    public interface OnSwipeListener {

         void onSwipeRight();

        void onSwipeLeft();

        void onSwipeTop();

        void onSwipeBottom();
    }
}

el cuando está configurado el ViewPager establece el swipeListener

postsPager.setOnSwipeListener(new ViewPagerNoSwipe.OnSwipeListener() {
            @Override
            public void onSwipeRight() {

              postsPager.setCurrentItem(postsPager.getCurrentItem() + 1,false);

            }

            @Override
            public void onSwipeLeft() {

            postsPager.setCurrentItem(postsPager.getCurrentItem() - 1, false);

            }
             ...
           }
Tamtom
fuente
0

Acabo de personalizar un poco el visor y deshabilito el deslizamiento fácilmente.

public class CustomViewPager extends ViewPager {

private boolean swipeLocked;

public CustomViewPager(Context context) {
    super(context);
}

public CustomViewPager(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);
}
}
Shivam Yadav
fuente
-1
shareViewPager?.setOnTouchListener(object :View.OnTouchListener{
            override fun onTouch(v: View?, event: MotionEvent?): Boolean {
                for (PAGE in 0..shareViewPager.adapter!!.count){
                    if (shareViewPager.currentItem==PAGE){
                        shareViewPager.setCurrentItem(PAGE-1,false)
                        shareViewPager.setCurrentItem(PAGE,false)
                    }}
                return true
            }

        })
Cihat Baydan
fuente