Est-il possible de désactiver le défilement sur un ViewPager

138

J'ai un ViewPagerqui instancie un View. Je voudrais désactiver momentanément le défilement du viewpager et les boutons enfants pendant qu'un résultat de recherche est renvoyé à la vue. J'ai appelé viewPager.setEnabled(false)mais cela ne le désactive pas.

Quelqu'un a une idée?

mAndroid
la source

Réponses:

356

Une solution simple est de créer votre propre sous - classe de ViewPagerqui a un private booleandrapeau, isPagingEnabled. Remplacez ensuite les méthodes onTouchEventet onInterceptTouchEvent. Si isPagingEnabledégal à true, invoquez la superméthode, sinon 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;
    }
}

Ensuite, dans votre Layout.XMLfichier, remplacez les <com.android.support.V4.ViewPager>balises par des <com.yourpackage.CustomViewPager>balises.

Ce code a été adapté de ce billet de blog .

Slayton
la source
2
grande solution, fonctionne très bien. Si vous voulez arrêter de glisser comme un singe, vous pouvez remplacer un OnPageChangeListener avec @Override public void onPageScrollStateChanged (état final int) {switch (état) {case ViewPager.SCROLL_STATE_SETTLING: mPager.setPagingEnabled (false); Pause; case ViewPager.SCROLL_STATE_IDLE: mPager.setPagingEnabled (true); Pause; } // noop}
Informatic0re
13
PS: En XML, utilisez <yourpkgname.CustomViewPager ... au lieu de <com.android, support.v4.ViewPager ...
thecr0w
pour ajouter une autre solution similaire, vous pouvez utiliser la bibliothèque appelée "JazzyViewPager": github.com/jfeinstein10/JazzyViewPager , et appeler simplement setPagingEnabled (boolean)
développeur android
est-il possible d'arrêter le défilement vers la droite uniquement? Je peux faire défiler vers la gauche seulement
Saif Hamed
Il est toujours possible de "faire défiler" en focalisant des éléments (boutons, etc.) dans les pages lors de l'utilisation d'un contrôleur de jeu ou d'un clavier par exemple. Comment désactiver cela complètement? Je suppose que c'est un autre type d'événement qui devrait être intercepté ...
David Ferrand
34

Il existe une solution simple pour celui-ci:

Lorsque vous souhaitez désactiver le défilement du visualiseur, alors:

mViewPager.setOnTouchListener(new OnTouchListener() {

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

Et lorsque vous souhaitez le réactiver, alors:

mViewPager.setOnTouchListener(null);

Cela fera l'affaire.

Akhil Sekharan
la source
46
Presque, mais pas tout à fait. Le toucher vers le bas se produit toujours, vous pouvez donc déplacer des pages en effectuant de nombreux petits mouvements.
Flynny75
@Akhil Sekharan faisait face au problème exactement à quoi Flynny est confronté en utilisant cette réponse .. mais heureusement, je ne sais pas à quel point cette erreur est partie .. :) et a fonctionné comme un charme !!
Zombie
Vous pouvez faire beaucoup de petits balayages pour que vous ayez toujours à passer sur le booléen public onInterceptTouchEvent (événement MotionEvent) {ride selon la réponse des slatons
Ryan Heitner
28

Voici ma variante légère de la réponse 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);
    }
}

Avec mon code, vous pouvez désactiver la pagination avec setEnable().

rekire
la source
Le remplacement onInterceptTouchEvent()empêchera les vues enfants de recevoir une entrée. Dans la plupart des cas, ce n'est pas le comportement prévu.
Alex Semeniuk
19

J'ai trouvé une solution simple.

//disable swiping
mViewPager.beginFakeDrag();

//enable swiping
mViewPager.endFakeDrag();
Yessy
la source
Est-ce tout le code que vous avez utilisé? Cela ne fonctionne pas pour moi.
Jared Burrows
17
Ça ne marche pas pour moi. Je peux toujours faire beaucoup de petits balayages.
DYS
Ce code n'est pas correct bcz Il défile très lentement comme une vue suspendue
Ghanshyam Nayma
Cela peut fonctionner par chance. La mise à jour vers ViewPager peut briser ce hack.
Pointer Null
Ça traîne encore mais petit à petit (.
ekashking
14

Je suggère une autre façon de résoudre ce problème. L'idée est d'encapsuler votre viewPager par un scrollView, de sorte que lorsque ce scrollView n'est pas défilable, votre viewPager ne le soit pas non plus.

Voici ma mise en page 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>

Aucun code nécessaire.

Fonctionne bien pour moi.

M. Marmor
la source
1
Parmi toutes ces réponses, je pense que c'est simple et fonctionne très bien !!
SREE
OK ... MAIS quand vous avez une carte comme l'un des fragments dans ViewPager alors ... c'est un problème
ekashking
4

Pour désactiver le balayage

 mViewPager.beginFakeDrag();

Pour activer le balayage

 mViewPager.endFakeDrag();
Isaias Carrera
la source
2
Le défilement est toujours possible, ce n'est tout simplement plus couramment. Cela ne fait qu'aggraver la qualité sans résoudre le problème.
Benjamin Basmaci
1
réponse dupliquée
Ricardo A.
3

La meilleure solution qui a fonctionné pour moi est:

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

Après cela, le défilement sera désactivé au toucher et vous pourrez toujours utiliser la setCurrentItemméthode pour changer de page.

Pradeep Kumar Kushwaha
la source
Je ne sais pas pourquoi, mais cela n'a tout simplement pas fonctionné. Le défilement se produit toujours.
Ricardo A.
1
La canScrollHorizontally()méthode n'a aucun effet dans le scénario actuel. Il n'est même pas appelé lorsque le balayage se produit.
Alex Semeniuk
3

Voici une réponse dans Kotlin et 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
la source
2

Que diriez-vous de ceci:
j'ai utilisé CustomViewPager
et ensuite, remplacer la méthode scrollTo
J'ai vérifié le mouvement en effectuant beaucoup de petits balayages, il ne défile pas vers d'autres pages.

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);
       }
    }
}
Au revoir
la source
J'ai eu le problème que le viewpager faisait encore de petits balayages, mais la neutralisation a View.scrollTo(int x, int y)résolu ce problème pour moi. Merci
Palm
Cela provoque un comportement étrange dans certains cas. Comme aller dans le vide et ne laisser qu'une page blanche '-'
Ricardo A.
2

Dans mon cas d'utilisation de ViewPager 2 alpha 2, l'extrait ci-dessous fonctionne

viewPager.isUserInputEnabled = false

Possibilité de désactiver l'entrée utilisateur (setUserInputEnabled, isUserInputEnabled)

reportez-vous à ceci pour plus de changements dans viewpager2 1.0.0-alpha02

Quelques modifications ont également été apportées à la dernière version de ViewPager 2 alpha 4

orientation et les attributs isUserScrollable ne font plus partie de SavedState

reportez-vous à ceci pour plus de changements dans viewpager2 # 1.0.0-alpha04

Piyush Johnson
la source
1

La nouvelle classe ViewPager2 d'Androidx permet de désactiver le défilement avec la méthode setUserInputEnabled (false)

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

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

La réponse de slayton fonctionne très bien. Si vous voulez arrêter de glisser comme un singe, vous pouvez remplacer un OnPageChangeListener avec

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

Vous ne pouvez donc glisser que côte à côte

Informatic0re
la source
1
Je n'ai trouvé aucune méthode de ViewPager telle que setPagingEnabled (valeur booléenne)
Rakesh Yadav
setPagingEnabled (valeur booléenne) doit être créé par vous, car il n'y a pas de méthode à remplacer.
Kharak
On setPagingEnabled()ne sait pas ce que fait cette méthode. Veuillez inclure le code complet.
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*/);
    }
}
}

Ensuite, dans votre fichier Layout.XML, remplacez les balises --- com.android.support.V4.ViewPager --- par --- com.yourpackage.NonSwipeableViewPager --- balises.

masoud jabbarian
la source