web-dev-qa-db-fra.com

Comment désactiver ViewPager de glisser dans une direction

Je veux autoriser l'utilisateur à glisser dans un ViewPager uniquement de droite à gauche. Donc, une fois qu'il a passé une page, il ne peut plus y revenir. Comment cela peut-il être fait?

J'ai essayé cette solution :

public class CustomViewPager extends ViewPager {

float lastX = 0;

boolean lockScroll = false;

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

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

@Override
public boolean onTouchEvent(MotionEvent ev) {

    switch (ev.getAction()) {
    case MotionEvent.ACTION_DOWN:
        lastX = ev.getX();
        lockScroll = false;
        return super.onTouchEvent(ev);
    case MotionEvent.ACTION_MOVE:

        if (lastX > ev.getX()) {
            lockScroll = false;
        } else {
            lockScroll = true;
        }

        lastX = ev.getX();
        break;
    }

    lastX = ev.getX();

    if(lockScroll) {
        return false;
    } else {
        return super.onTouchEvent(ev);
    }
}
}

Mais cela me permet quand même de mal glisser dans l'autre sens.

30
Emil Adz

Il y a un autre événement que vous manquez: onInterceptTouchEvent. Il doit contenir la même logique que onTouchEvent.

Ma solution complète est basée sur cette réponse. Il vous permettra d'activer/désactiver la pagination dans n'importe quelle direction et à tout moment.

1. Créer une énumération

 public enum SwipeDirection {
    all, left, right, none ;
}

2.Extend ViewPager

public class CustomViewPager extends ViewPager {

    private float initialXValue;
    private SwipeDirection direction;

    public CustomViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.direction = SwipeDirection.all;
    }

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

        return false;
    }

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

        return false;
    }

    private boolean IsSwipeAllowed(MotionEvent event) {
        if(this.direction == SwipeDirection.all) return true;

        if(direction == SwipeDirection.none )//disable any swipe
            return false;

        if(event.getAction()==MotionEvent.ACTION_DOWN) {
            initialXValue = event.getX();
            return true;
        }

        if(event.getAction()==MotionEvent.ACTION_MOVE) {
            try {
                float diffX = event.getX() - initialXValue;
                if (diffX > 0 && direction == SwipeDirection.right ) {
                    // swipe from left to right detected
                    return false;
                }else if (diffX < 0 && direction == SwipeDirection.left ) {
                    // swipe from right to left detected
                    return false;
                }
            } catch (Exception exception) {
                exception.printStackTrace();
            }
        }

        return true;
    }

    public void setAllowedSwipeDirection(SwipeDirection direction) {
        this.direction = direction;
    }

3.Utilisez votre viewPager dans une mise en page

 <package_name.customviewpager 
     Android:id="@+id/customViewPager" 
     Android:layout_height="match_parent" 
     Android:layout_width="match_parent" />

4. Activez n'importe quelle direction de balayage dans le code. La valeur par défaut est tout (droite et gauche)

mViewPager.setAllowedSwipeDirection(SwipeDirection.right);
70
andre719mv
package com.contacts_app.jamison.contacts__proprivacy4;

import Android.content.Context;
import Android.content.res.Resources;
import Android.support.v4.view.ViewPager;
import Android.util.AttributeSet;
import Android.util.Log;
import Android.view.MotionEvent;

public class ViewPager_Settings extends ViewPager
{
private final String TAG = ViewPager_Settings.class.getSimpleName();
public float startX;

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

 ////////////////////////////////////////////////////////////////////////////////////////////////
public static int dpTOpx(double dp)
{
    return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
}
public static int pxTOdp(double px)
{
    return (int) (px / Resources.getSystem().getDisplayMetrics().density);
}
////////////////////////////////////////////////////////////////////////////////////////////////

/*****DispatchTouchEvent for the View Pager to intercept and block swipes Right*****/
@Override
public boolean dispatchTouchEvent(MotionEvent ev)
{
    final int actionMasked = ev.getActionMasked() & MotionEvent.ACTION_MASK;
    //int movement_limit = pxTOdp(50);
    switch (actionMasked)
    {
        case (MotionEvent.ACTION_DOWN):
        {
            startX = ev.getX();
            Log.i(TAG, "startX: " + startX);

            /*Should always be this below*/
            return super.dispatchTouchEvent(ev);
        }
        case (MotionEvent.ACTION_MOVE):
        {
            Log.i(TAG, "ev.getX() - startX:" + (ev.getX() - startX));

            /*Switching directional changes would be a matter of flipping the  "<" sign in the line below.*/
            if (ev.getX() - startX > 0)
            {
                /*The result is that the ViewPager will not swipe from left*/
                ev.setAction(MotionEvent.ACTION_CANCEL);;
            }

            /*Should always be this below*/
            super.dispatchTouchEvent(ev);
        }
        /**The ACTION_UP case statement is only needed if you don't want to pass down the touch event 
        * to buttons that may receive the click after the swipe is blocked.*/
        /*case (MotionEvent.ACTION_UP):
        {
            //Log.i(TAG, "movement_limit: " + movement_limit);

            //(-50) may need to be changed to something more broader in scope to accompany all screen densities
            if ( (ev.getX() - startX) < (-50) )
            {
                ev.setAction(MotionEvent.ACTION_CANCEL);
            }

            //Should always be this below
            super.dispatchTouchEvent(ev);
        }*/
    }
    /*Should always be this below*/
    return super.dispatchTouchEvent(ev);
}
 ////////////////////////////////////////////////////////////////////////////////////////////////

}/*****END OF FILE*****/

N'oubliez pas de modifier la ligne en haut pour mettre le nom du package de votre application. De plus, la plupart, sinon la totalité, des commentaires donnent un aperçu de ce que fait le code au cas où vous décideriez de bricoler.

1
JamisonMan111

Définissez votre adaptateur comme ceci

public class MyFragmentStatePagerAdapter extends FragmentStatePagerAdapter {

    private final int totalPages = 10;
    private int currentPage = 0;

    public MyFragmentStatePagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int position) {
        // Use whatever logic you want here to
        // to select a fragment based on
        // currentPage instead of position

        if (currentPage % 2 == 0) {
            return new Fragment1();
        } else {
            return new Fragment2();
        }
    }

    @Override
    public int getCount() {
        return currentPage == totalPages ? 1 : 2;
    }

    @Override
    public int getItemPosition(Object object){
        return PagerAdapter.POSITION_NONE;
    }

    public void nextPage() {
        currentPage++;
        notifyDataSetChanged();
    }
}

Dans le fragment qui utilise le pager de vue, procédez comme suit

@Override
public void onPageSelected(int arg0) {
    if (arg0 > 0) {
        pagerAdapter.nextPage();
        pager.setCurrentItem(0, false);
    }
}
0
mpkuth

Essayez d'ajouter (la même logique que dans onTouchEvent)

@Override
public boolean onInterceptTouchEvent(MotionEvent arg0) {
    // allow/ not allow swiping to switch between pages
    return !lockScroll ;
}
0
NickF