web-dev-qa-db-fra.com

Balayer la direction dans ViewPager

J'ai une application Android qui utilise ViewPager et FragmentStatePagerAdapter. J'ai cependant besoin d'ajouter une nouvelle fonctionnalité dans laquelle je dois connaître la direction du balayage pour passer d'une vue fragmentée à une autre, à gauche ou à droite. (c’est-à-dire que lorsque je balayerais à gauche, je ferais une chose et quand je balayerais à droite je ferais autre chose).

Veuillez noter que je n'ai pas besoin que les événements se produisent APRÈS que le balayage soit terminé. Je dois faire ces événements au fur et à mesure que le balayage se produit. J'ai pensé à utiliser setOnPageChangeListener() mais cela ne me dit pas la direction du balayage. Pouvez-vous me conseiller s'il vous plaît sur la façon de déterminer la direction de balayage?

Merci.

14
Greeso

Examinez la méthode onPageSelected(int position) de ViewPager.OnPageChangeListener . La position donne l'index de la nouvelle page sélectionnée. Si vous conservez une trace de l'index de page actuel, vous pouvez le comparer à l'index position pour obtenir la direction gauche/droite du balayage. 

Maintenant que vous mentionnez OnPageChangeListener ne vous aide pas, considérez la méthode onInterceptTouchEvent (MotionEvent ev) de ViewPager. Prenez en compte les ACTION_DOWN, ACTION_MOVE et ACTION_UP de MotionEvent. J'espère que cela t'aides.

6
Vino

J'ai rencontré ce problème et j'ai besoin de connaître la direction du balayage tel qu'il se passait afin d'éviter de glisser dans une certaine direction. Voici comment j'ai résolu mon problème, espérons que cela soit utile à quelqu'un. J'ai trouvé tous les exemples précédents inefficaces pour ce dont j'avais besoin.

Si vous sous-classez votre ViewPager, vous pouvez répondre aux méthodes onInterceptTouchEvent(MotionEvent event) et onTouchEvent(MotionEvent event) de ViewPager.

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    boolean wasSwipeToRight = this.wasSwipeToRightEvent(event));
    // Do what you want here with left/right swipe

    return super.onInterceptTouchEvent(event);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    boolean wasSwipeToRight = this.wasSwipeToRightEvent(event));
    // Do what you want here with left/right swipe

    return super.onTouchEvent(event);
}

Voici la méthode appelée pour déterminer la direction de l'événement.

// Stores the starting X position of the ACTION_DOWN event
float downX;

/**
 * Checks the X position value of the event and compares it to
 * previous MotionEvents. Returns a true/false value based on if the 
 * event was an swipe to the right or a swipe to the left.
 *
 * @param event -   Motion Event triggered by the ViewPager
 * @return      -   True if the swipe was from left to right. False otherwise
 */
private boolean wasSwipeToRightEvent(MotionEvent event){
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            downX = event.getX();
            return false;

        case MotionEvent.ACTION_MOVE:
        case MotionEvent.ACTION_UP:
            return downX - event.getX() > 0;

        default:
            return false;
    }
}
5
drees

Ceci est assez simple avec l'introduction d'une variable d'instance pour garder une trace de la page en cours. 

public class MyActivity extends Activity implements ViewPager.OnPageChangeListener {

    private ViewPager viewPager;
    private int currentPosition;


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Do trivial stuff
        .
        .
        .
        viewPager.setOnClickListener(this); // doesnt have to be in onCreate
    }

    @Override
    public void onPageSelected(int position) {
        if(currentPosition < position) {
            // handle swipe LEFT
        } else if(currentPosition > position){
            // handle swipe RIGHT
        }
        currentPosition = position; // Update current position
    }
}
2
TomTaila

Peut-être que vous pouvez créer un auditeur comme ceci:

buttonIcons.setOnTouchListener(new OnTouchListener() {

        @Override
        public boolean onTouch(final View v, final MotionEvent event) {
            switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                downX = event.getX();

                return true;

            case MotionEvent.ACTION_UP:

                upX = event.getX();
                final float deltaX = downX - upX;

                if (deltaX > 0 && deltaX > SWIPE_MIN_DISTANCE) {

                    final Animation loadInAnimation = AnimationUtils
                            .loadAnimation(
                                    activity.this,
                                    R.anim.slide_in_right);
                    final Animation loadOutAnimation = AnimationUtils
                            .loadAnimation(
                                    activity.this,
                                    R.anim.slide_out_left);

                    viewFlipper.setInAnimation(loadInAnimation);
                    viewFlipper.setOutAnimation(loadOutAnimation);
                    viewFlipper.showPrevious();

                    startSaveButtonAnimation();

                }
                if (deltaX < 0 && -deltaX > SWIPE_MIN_DISTANCE) {

                    final Animation loadInAnimation = AnimationUtils
                            .loadAnimation(
                                    activity.this,
                                    R.anim.slide_in_left);
                    final Animation loadOutAnimation = AnimationUtils
                            .loadAnimation(
                                    activity.this,
                                    R.anim.slide_out_right);

                    viewFlipper.setInAnimation(loadInAnimation);
                    viewFlipper.setOutAnimation(loadOutAnimation);
                    viewFlipper.showNext();

                    startSaveButtonAnimation();

                }
                return true;

            }

            return false;
        }
    });
2
axl coder

Vous pouvez ajouter un module OnPageChangeListner au ViewPager et procéder comme suit:

mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        float tempPositionOffset = 0;

        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            if (position == 0) {
                if (tempPositionOffset < positionOffset) {
                    Log.d("eric", "scrolling left ...");
                } else {
                    Log.d("eric", "scrolling right ...");
                }

                tempPositionOffset = positionOffset;

           Log.d("eric", "position " + position + "; " + " positionOffset " + positionOffset + "; " + " positionOffsetPixels " + positionOffsetPixels + ";");
            }
        }

        @Override
        public void onPageSelected(int position) {

        }

        @Override
        public void onPageScrollStateChanged(int state) {

        }
    });
1
Eric Liu

Vous pouvez réellement trouver une direction en utilisant les paramètres de onPageScrolled.
L'auditeur suivant est configuré pour afficher le message du journal une fois par direction du changement de fragment de réseau (à gauche si les fragments laissés sont révélés, au centre si aucun fragment ne les révèle, à droite si les fragments à droite révèlent).
Variables de classe, nécessité de garder une trace 

    // -1 - left, 0 - center, 1 - right
    private int scroll = 0; 
    // set only on `onPageSelected` use it in `onPageScrolled` 
    // if currentPage < page - we swipe from left to right
    // if currentPage == page - we swipe from right to left  or centered
    private int currentPage = 0; 
    // if currentPage < page offset goes from `screen width` to `0`
    // as you reveal right fragment. 
    // if currentPage == page , offset goes from `0` to `screen width`
    // as you reveal right fragment
    // You can use it to see 
    //if user continue to reveal next fragment or moves it back
    private int currentOffset = 0;
    // behaves similar to offset in range `[0..1)`
    private float currentScale = 0;

L'auditeur

pager.addOnPageChangeListener(
            new OnPageChangeListener(){

                @Override
                public void onPageScrolled(int page, float scale, int offset){


                    if(scale != 0f && offset > 10){


                        if(currentOffset > offset && currentScale > scale && (page + 1) == currentPage){


                            if(scroll != -1){
                                newImageSet = true;
                                scroll = -1;
                                Log.e("scroll", "left");
                            }
                        } else if(currentOffset < offset && currentScale < scale && page == currentPage){


                            if(scroll != 1){
                                newImageSet = true;
                                scroll = 1;
                                Log.e("scroll", "right");

                            }
                        }
                        currentOffset = offset;
                        currentScale = scale;



                }


                @Override
                public void onPageSelected(int i){
                    Log.e("scroll","centre");
                    // we are centerd, reset class variables
                    currentPage = i;
                    currentScale = 0;
                    currentOffset = 0;
                    scroll = 0;


                }


                @Override
                public void onPageScrollStateChanged(int i){

                }
            }
        );
1
Yarh

J'utilise cette petite implémentation pour détecter si l'utilisateur fait défiler vers la droite ou vers la gauche pendant le défilement lui-même. Je peux avoir des bugs lors de certaines conditions dont je ne suis pas au courant, mais c'est ce que je pourrais trouver pour ce dont j'avais besoin sans avoir à ajouter un écouteur tactile:

viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {

        int SCROLLING_RIGHT = 0;
        int SCROLLING_LEFT = 1;
        int SCROLLING_UNDETERMINED = 2;

        int currentScrollDirection = 2;

        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            if (isScrollDirectionUndetermined()){
                setScrollingDirection(positionOffset);
            }



            if (isScrollingLeft()){
                Log.i("TabLayout","Scrolling LEFT");
            }
            if (isScrollingRight()){
                Log.i("TabLayout","Scrolling RIGHT");

            }

        }

        private void setScrollingDirection(float positionOffset){
            if ((1-positionOffset)>= 0.5){
                this.currentScrollDirection = SCROLLING_RIGHT;
            }
            else if ((1-positionOffset)<= 0.5){
                this.currentScrollDirection =  SCROLLING_LEFT;
            }
        }

        private boolean isScrollDirectionUndetermined(){
            return currentScrollDirection == SCROLLING_UNDETERMINED;
        }

        private boolean isScrollingRight(){
            return currentScrollDirection == SCROLLING_RIGHT;
        }

        private boolean isScrollingLeft(){
            return currentScrollDirection == SCROLLING_LEFT;
        }

        @Override
        public void onPageSelected(int position) {
        }

        @Override
        public void onPageScrollStateChanged(int state) {
            if (state == ViewPager.SCROLL_STATE_IDLE){
                this.currentScrollDirection = SCROLLING_UNDETERMINED;
            }
        }

    });

Nous pouvons détecter le sens de défilement car lorsque l'utilisateur fait défiler de gauche à droite la positionOffset va de 0 à> 1 et en défilant de droite à gauche de 1 à 0. Nous pouvons ensuite vérifier cette valeur une fois au tout début d'un défilement et réinitialiser le drapeau uniquement à la fin du défilement.

Nous avons défini currentScrollDirection sur indéterminé à la position inactive au lieu de onPageSelected car onPageSelected peut être appelé si l'utilisateur relâche au milieu d'un parchemin et vous obtiendrez une lecture fausse.

0
Amro elaswar