Question Comment désactiver la pagination en balayant avec le doigt dans ViewPager tout en étant capable de balayer par programmation?


J'ai ViewPager et en dessous j'ai 10 boutons. En cliquant sur le bouton, par exemple # 4, le téléavertisseur passe immédiatement à la page 4 par mPager.setCurrentItem(3);. Mais, je veux désactiver la pagination en balayant avec le doigt horizontalement. Ainsi, la pagination est faite SEULEMENT en cliquant sur les boutons. Alors, comment puis-je désactiver le balayage avec le doigt?


417
2018-03-10 21:18


origine


Réponses:


Vous devez sous-classer ViewPager. OnTouchEvent a beaucoup de bonnes choses que vous ne voulez pas changer, comme permettre aux enfants de toucher. OnInterceptTouchEvent est ce que vous voulez changer. Si vous regardez le code de ViewPager, vous verrez le commentaire:

    /*
     * 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.
     */

Voici une solution complète:

Tout d'abord, ajoutez cette classe à votre dossier 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*/);
        }
    }
}

Ensuite, assurez-vous d'utiliser cette classe au lieu du ViewPager standard, que vous avez probablement spécifié comme android.support.v4.view.ViewPager. Dans votre fichier de disposition, vous devrez le spécifier avec quelque chose comme:

<com.yourcompany.NonSwipeableViewPager
    android:id="@+id/view_pager"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="1" />

Cet exemple particulier se trouve dans un LinearLayout et vise à occuper la totalité de l’écran, ce qui explique pourquoi layout_weight est à 1 et layout_height à 0dp.

Et setMyScroller (); méthode pour une transition en douceur


752
2018-03-10 22:49



L'extension plus générale de ViewPager serait de créer un SetPagingEnabled méthode pour que nous puissions activer et désactiver la pagination à la volée. Pour activer / désactiver le balayage, remplacez simplement deux méthodes: onTouchEvent et onInterceptTouchEvent. Les deux retourneront "faux" si la pagination a été désactivée.

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

Ensuite, sélectionnez cette option au lieu du visualiseur intégré en XML

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

Il vous suffit d'appeler le setPagingEnabled méthode avec false et les utilisateurs ne pourront pas glisser pour paginer.


402
2017-11-18 06:27



Le moyen le plus simple est de setOnTouchListener et retour true pour ViewPager.

mPager.setOnTouchListener(new OnTouchListener()
    {           
        @Override
        public boolean onTouch(View v, MotionEvent event)
        {
            return true;
        }
    });

88
2017-11-15 05:49



Mieux vaut le déclarer stylé pour pouvoir modifier sa propriété à partir 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;
}

Et dans vos valeurs / attr.xml:

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

afin que vous puissiez l'utiliser dans votre mise en page 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" />

Bien sûr, vous pouvez toujours avoir une propriété get / set.


51
2017-09-08 10:49



Surcharge uniquement onTouchEvent et onInterceptTouchEvent n'est pas suffisant si vous avez ViewPager dans un autre ViewPager. Child ViewPager déroberait les événements tactiles de défilement horizontaux à partir du parent ViewPager à moins qu'il ne soit positionné sur sa première / dernière page.

Pour que cette configuration fonctionne correctement, vous devez également ignorer canScrollHorizontally méthode.

Voir LockableViewPager mise en œuvre ci-dessous.

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

}

39
2018-01-05 10:45



Pour désactiver le balayage

mViewPager.beginFakeDrag();

Pour activer le balayage

mViewPager.endFakeDrag();

23
2018-03-16 07:57



Si vous étendez à partir de ViewPager, vous devez également passer outre executeKeyEvent comme indiqué précédemment par @araks

@Override
public boolean executeKeyEvent(KeyEvent event)
{
    return isPagingEnabled ? super.executeKeyEvent(event) : false;
}

Parce que certains appareils comme le Galaxy Tab 4 10 'affichent ces boutons là où la plupart des appareils ne les affichent jamais:

Keyboard buttons


21
2017-08-01 18:16



Je devais désactiver le balayage sur une page spécifique, et lui donner une belle animation en caoutchouc, voici comment:

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

13
2018-06-26 21:07



Je sais qu'il est très tard pour publier ceci, mais voici un tout petit bidouillage pour atteindre votre résultat;)

Ajoutez simplement une vue fictive au dessous de votre 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>

Puis ajoutez un OnClickListener à ton RelativeLayout.

dummyView = (RelativeLayout) findViewById(R.id.dummyView);

dummyView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
         //Just leave this empty
    }
});

Obtenez un peu de créativité avec les mises en page, leurs emplacements et leur comportement et vous apprendrez à trouver un moyen de faire absolument tout ce que vous imaginez :)

Bonne chance!


11
2018-05-12 03:33