Прокручивание направления в ViewPager

У меня есть приложение для Android, которое использует ViewPager и FragmentStatePagerAdapter. Однако мне нужно добавить новую функцию, в которой я должен знать направление движения, чтобы перейти от одного фрагмента к другому, влево или вправо. (то есть, когда я прокручиваю влево, я сделаю одно, а когда я проведу правой рукой, я сделаю что-то еще).

Обратите внимание: мне не нужны события, чтобы произойти ПОСЛЕ завершения салфетки. Я должен делать эти события, когда происходит салфетка. Я думал об использовании setOnPageChangeListener(), но он не говорит мне о том, как двигаться. Можете ли вы посоветовать мне, пожалуйста, как определить направление движения?

Спасибо.

Ответ 1

Взгляните на метод onPageSelected(int position) ViewPager.OnPageChangeListener. position указывает индекс только что выбранной страницы. Если вы отслеживаете текущий индекс страницы, вы можете сравнить его с индексом position, чтобы получить направление влево/вправо.

Теперь, когда вы указываете, что OnPageChangeListener не помогает, рассмотрите метод onInterceptTouchEvent (MotionEvent ev) ViewPager. Учитывайте MotionEvent ACTION_DOWN, ACTION_MOVE и ACTION_UP. Надеюсь, это поможет.

Ответ 2

Я столкнулся с этой проблемой и должен знать направление движения, как это происходило, чтобы предотвратить прокрутку в определенном направлении. Вот как я решил свою проблему, надеюсь, это полезно кому-то. Я нашел все предыдущие примеры неэффективными для того, что мне было нужно.

Если вы подклассифицируете ViewPager, вы можете ответить на onInterceptTouchEvent(MotionEvent event) и onTouchEvent(MotionEvent event) методы 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);
}

Вот метод, который вызывается для определения направления события.

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

Ответ 3

Возможно, вы можете создать слушателя следующим образом:

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

Ответ 4

Фактически вы можете найти направление с использованием параметров onPageScrolled.
Следующий слушатель установлен для отображения лог-сообщения один раз на направление изменения чистого фрагмента (слева, если левые фрагменты отображаются, в центре, если фрагмент не отображается, справа, если показывает правый фрагмент).
Переменные класса, необходимо отслеживать

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

Слушатель

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){

                }
            }
        );

Ответ 5

Это достаточно просто с введением переменной экземпляра, чтобы отслеживать текущую страницу.

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

Ответ 6

Вы можете добавить OnPageChangeListner в ViewPager и сделать что-то вроде этого:

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) {

        }
    });

Ответ 7

Я использую эту небольшую реализацию, чтобы определить, прокручивается ли пользователь вправо или влево во время самой прокрутки. У меня могут быть некоторые ошибки при определенных условиях, о которых я не знаю, но это то, что я мог бы придумать для того, что мне было нужно, не добавляя слушателя касания:

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

    });

Мы можем определить направление прокрутки, потому что, когда пользователь прокручивается слева направо, positionOffset переходит из 0 → 1, а при прокрутке справа налево он переходит от 1 → 0. Затем мы можем проверить это значение один раз в самом начале прокрутки и reset флаг только в конце прокрутки.

Мы устанавливаем currentScrollDirection неопределенным в позиции idle вместо onPageSelected, потому что onPageSelected может вызываться, если пользователь освобождается в середине прокрутки, а затем вы получите ложное показание.

Ответ 8

Вы можете использовать setOnPageChangeListener() и правильно реализовать onPageScrolled(int position, float positionOffset, int positionOffsetPixels).

Вы можете определить направление по положениюOffset и положению:

public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
{
   if(position == mCurrentPosition && positionOffset > 0)
   {
    //swipe right
   }
   else if (positionOffset > 0)
   {
   //swipe left
   }
}