¿Es posible deshabilitar el desplazamiento en un ViewPager

138

Tengo un ViewPagerque instancia a View. Me gustaría deshabilitar momentáneamente el desplazamiento del visor y los botones secundarios mientras se devuelve un resultado de búsqueda a la vista. Estoy llamando viewPager.setEnabled(false)pero esto no lo deshabilita.

¿Alguien tiene alguna idea?

mAndroid
fuente

Respuestas:

355

Una solución sencilla es crear su propia subclase de ViewPagerque tiene una private booleanbandera, isPagingEnabled. Luego anule los métodos onTouchEventy onInterceptTouchEvent. Si isPagingEnabledes igual a verdadero invoque el supermétodo, de lo contrario return.

public class CustomViewPager extends ViewPager {

    private boolean isPagingEnabled = true;

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

    public CustomViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return this.isPagingEnabled && super.onTouchEvent(event);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        return this.isPagingEnabled && super.onInterceptTouchEvent(event);
    }

    public void setPagingEnabled(boolean b) {
        this.isPagingEnabled = b;
    }
}

Luego, en su Layout.XMLarchivo, reemplace las <com.android.support.V4.ViewPager>etiquetas con <com.yourpackage.CustomViewPager>etiquetas.

Este código fue adaptado de esta publicación de blog .

slayton
fuente
2
Gran solución, funciona bien. Si desea dejar de deslizarse como un mono, puede anular un OnPageChangeListener con @Override public void onPageScrollStateChanged (final int state) {switch (state) {case ViewPager.SCROLL_STATE_SETTLING: mPager.setPagingEnabled (false); descanso; case ViewPager.SCROLL_STATE_IDLE: mPager.setPagingEnabled (verdadero); descanso; } // noop}
Informatic0re
13
PD: en XML, use <yourpkgname.CustomViewPager ... en lugar de <com.android, support.v4.ViewPager ...
thecr0w
para agregar otra solución similar, puede usar la biblioteca llamada "JazzyViewPager": github.com/jfeinstein10/JazzyViewPager , y simplemente llamar a setPagingEnabled (boolean)
desarrollador de Android
¿Es posible dejar de desplazarse solo correctamente? solo puedo desplazarme a la izquierda
Saif Hamed
Todavía es posible "desplazarse" enfocando elementos (botones, etc.) en las páginas cuando se usa un controlador de juego o teclado, por ejemplo. ¿Cómo deshabilitar eso por completo? Supongo que es otro tipo de evento que debería ser interceptado ...
David Ferrand
34

Hay una solución fácil para este:

Cuando desee deshabilitar el desplazamiento del visor, entonces:

mViewPager.setOnTouchListener(new OnTouchListener() {

   public boolean onTouch(View arg0, MotionEvent arg1) {
      return true;
   }
}); 

Y cuando quieras volver a habilitarlo, entonces:

mViewPager.setOnTouchListener(null);

Eso hará el truco.

Akhil Sekharan
fuente
46
Casi, pero no del todo. El toque aún ocurre, por lo que puede mover páginas haciendo muchos pequeños deslizamientos.
Flynny75
@Akhil Sekharan Estaba enfrentando el problema exactamente a lo que se enfrenta Flynny al usar esta respuesta ... pero afortunadamente no sé cuán repentinamente se ha ido ese error ... :) ¡y funcionó de maravilla!
Zombie
Puede hacer muchos pequeños golpes, por lo que aún tiene que pasar por un booleano público en InterceptTouchEvent (evento MotionEvent) {montar según la respuesta de slatons
Ryan Heitner
28

Aquí está mi variante ligera de la respuesta de slayton:

public class DeactivatableViewPager extends ViewPager {
    public DeactivatableViewPager(Context context) {
        super(context);
    }

    public DeactivatableViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return !isEnabled() || super.onTouchEvent(event);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        return isEnabled() && super.onInterceptTouchEvent(event);
    }
}

Con mi código puede deshabilitar la paginación con setEnable().

rekire
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
19

Encontré una solución simple.

//disable swiping
mViewPager.beginFakeDrag();

//enable swiping
mViewPager.endFakeDrag();
Sessy
fuente
¿Es este todo el código que usaste? Esto no está funcionando para mí.
Jared Burrows
17
No funciona para mi Todavía puedo hacer muchos pequeños golpes.
DYS
Este código no es apropiado porque se desplaza muy lentamente como una vista colgante
Ghanshyam Nayma
Esto puede funcionar por suerte. Actualizar a ViewPager puede romper este truco.
Puntero nulo
Todavía está arrastrando, pero poco a poco (.
ekashking
14

Sugiero otra forma de resolver este problema. La idea es envolver su viewPager con un scrollView, de modo que cuando este scrollView no sea desplazable, su viewPager tampoco sea desplazable.

Aquí está mi diseño XML:

        <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/viewPager"
                android:layout_width="wrap_content"
                android:layout_height="match_parent" />

        </HorizontalScrollView>

No se necesita código.

Funciona bien para mi.

M. Marmor
fuente
1
Entre todas estas respuestas, ¡siento que esto es simple y funciona bien!
SREE
Bien ... pero cuando se tiene un mapa como uno de los fragmentos en ViewPager entonces ... es un problema
ekashking
4

Para deshabilitar deslizar

 mViewPager.beginFakeDrag();

Para habilitar deslizar

 mViewPager.endFakeDrag();
Isaias Carrera
fuente
2
El desplazamiento todavía es posible, ya no es fluido. Esto básicamente está empeorando la calidad sin resolver el problema.
Benjamin Basmaci
1
respuesta duplicada
Ricardo A.
3

La mejor solución que funcionó para mí es:

public class DeactivatedViewPager extends ViewPager {

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

    public DeactivatedViewPager (Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean canScrollHorizontally(int direction) {
        return false;
    }
}

Después de esto, el desplazamiento se deshabilitará al tocarlo y aún podrá usar el setCurrentItemmétodo para cambiar de página.

Pradeep Kumar Kushwaha
fuente
No sé por qué, pero simplemente no funcionó. El desplazamiento todavía ocurre.
Ricardo A.
1
El canScrollHorizontally()método no tiene efecto en el escenario actual. Ni siquiera se llama cuando ocurre el deslizamiento.
Alex Semeniuk
3

Aquí hay una respuesta en Kotlin y androidX

import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import androidx.viewpager.widget.ViewPager

class DeactivatedViewPager @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null
) : ViewPager(context, attrs) {

    var isPagingEnabled = true

    override fun onTouchEvent(ev: MotionEvent?): Boolean {
        return isPagingEnabled && super.onTouchEvent(ev)
    }

    override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
        return isPagingEnabled && super.onInterceptTouchEvent(ev)
    }
}
Pasi Matalamäki
fuente
2

¿Qué tal esto?
Utilicé CustomViewPager
y luego, anule el método scrollTo
. Revisé el movimiento al hacer muchos pequeños deslizamientos, no se desplaza a otras páginas.

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

    @Override
    public void scrollTo(int x, int y) {
       if(enabled) {
          super.scrollTo(x, y);
       }
    }
}
Adiós
fuente
Tuve el problema de que el visor todavía estaba haciendo pequeños golpes, pero anularlo View.scrollTo(int x, int y)resolvió este problema para mí. Gracias
Palm
Causa un comportamiento extraño en algunos casos. Como ir al vacío y dejar solo una página en blanco '-'
Ricardo A.
2

En mi caso de usar ViewPager 2 alpha 2, el siguiente fragmento funciona

viewPager.isUserInputEnabled = false

Posibilidad de deshabilitar la entrada del usuario (setUserInputEnabled, isUserInputEnabled)

consulte esto para obtener más cambios en viewpager2 1.0.0-alpha02

También se realizaron algunos cambios en la última versión de ViewPager 2 alpha 4

Los atributos de orientación e isUserScrollable ya no forman parte de SavedState

consulte esto para obtener más cambios en viewpager2 # 1.0.0-alpha04

Piyush Johnson
fuente
1

La nueva clase ViewPager2 de androidx permite deshabilitar el desplazamiento con el método setUserInputEnabled (falso)

private val pager: ViewPager2 by bindView(R.id.pager)

override fun onCreate(savedInstanceState: Bundle?) {
    pager.isUserInputEnabled = false
}
shushper
fuente
0

La respuesta de slayton funciona bien. Si desea dejar de deslizarse como un mono, puede anular un OnPageChangeListener con

@Override public void onPageScrollStateChanged(final int state) { 
        switch (state) { 
            case ViewPager.SCROLL_STATE_SETTLING: 
                mPager.setPagingEnabled(false); 
                break; 
            case ViewPager.SCROLL_STATE_IDLE: 
                mPager.setPagingEnabled(true); 
                break; 
        } 
    }

Así que solo puedes deslizar uno al lado del otro

Informática
fuente
1
No encontré ningún método de ViewPager como setPagingEnabled (valor booleano)
Rakesh Yadav
setPagingEnabled (valor booleano) debe ser creado por usted, porque no hay tal método para anular.
Kharak
No está claro qué hace este setPagingEnabled()método. Por favor incluya el código completo.
Alex Semeniuk
0
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);
}

public NonSwipeableViewPager(Context context, AttributeSet attrs) {
    super(context, attrs);
}

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    // stop swipe 
    return false;
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    // stop switching pages
    return false;
}

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

Luego, en su archivo Layout.XML, reemplace las etiquetas --- com.android.support.V4.ViewPager --- con --- com.yourpackage.NonSwipeableViewPager --- etiquetas.

masoud jabbarian
fuente