web-dev-qa-db-fra.com

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

J'ai une ViewPager qui instancie une View. Je souhaite désactiver le défilement du visualiseur et des 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? 

121
mAndroid

Une solution simple consiste à créer votre propre sous-classe de ViewPager dotée d'un indicateur private boolean, isPagingEnabled. Puis substituez les méthodes onTouchEvent et onInterceptTouchEvent. Si isPagingEnabled est égal à true, appelez la méthode super, 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;
    }
}

Puis, dans votre fichier Layout.XML, remplacez les balises <com.Android.support.V4.ViewPager> par les balises <com.yourpackage.CustomViewPager>.

Ce code a été adapté de ce blog post

329
slayton

Il y a une solution facile pour celui-ci:

Lorsque vous souhaitez désactiver le défilement du viewpager, procédez comme suit:

mViewPager.setOnTouchListener(new OnTouchListener() {

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

Et quand vous voulez le réactiver, alors:

mViewPager.setOnTouchListener(null);

Cela fera l'affaire.

30
Akhil Sekharan

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().

28
rekire

J'ai trouvé une solution simple.

//disable swiping
mViewPager.beginFakeDrag();

//enable swiping
mViewPager.endFakeDrag();
20
Yessy

Je suggère une autre façon de résoudre ce problème. L'idée consiste à envelopper votre viewPager dans une scrollView, de sorte que lorsque cette scrollView ne peut pas défiler, 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 requis.

Fonctionne bien pour moi.

7
M. Marmor

Pour désactiver le balayage

 mViewPager.beginFakeDrag();

Pour activer le balayage

 mViewPager.endFakeDrag();
5
Isaias Carrera

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 méthode setCurrentItem pour changer de page.

Que dis-tu de ça : 
J'ai utilisé CustomViewPager 
et ensuite, surcharger la méthode scrollTo
J'ai vérifié le mouvement lorsque je faisais beaucoup de petits coups, cela ne défilait 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);
       }
    }
}
3
godbye

La réponse de Slayton fonctionne bien. Si vous voulez arrêter de glisser comme un singe, vous pouvez remplacer un OnPageChangeListener 

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

Donc, vous ne pouvez que glisser côte à côte

1
Informatic0re

Lorsque vous utilisez la réponse ci-dessus, vous pouvez être confronté à une mauvaise question: "set isScrollEnabled false, certaines vues de ce viewPager ne peuvent pas gérer onClick & onTouchEvent. Je vous présente donc ma solution, j'espère que cela pourra vous aider ... 

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

    var isScrollEnabled = true

    override fun onInterceptTouchEvent(event: MotionEvent?): Boolean {
        if(isScrollEnabled){ 
             super.onInterceptTouchEvent(event) 
         }else{
            return isScrollEnabled && super.onInterceptTouchEvent(event)
         }
    }
    override fun onTouchEvent(event: MotionEvent?): Boolean {
        if(isScrollEnabled){
             return isScrollEnabled
         }else{
             return isScrollEnabled  && super.onTouchEvent(event)
        }
    }
}
0
BertKing
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 des balises --- com.yourpackage.NonSwipeableViewPager ---.

0
masoud jabbarian

Remplacer uniquement onTouchEvent et onInterceptTouchEvent n'est pas suffisant si ViewPager est lui-même dans un autre ViewPager.

ViewPager enfant ferrait des événements tactiles avec défilement horizontal à partir du ViewPager parent, à moins qu’il ne soit positionné sur sa première/dernière page.

Voir plus dans cette SO réponse

0
sidon

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
}
0
shushper

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)
    }
}
0
Pasi Matalamäki