34

我正在使用 ViewPager(支持库)。我想知道每次 ViewPager 更改可见页面时,它是向左还是向右滚动。

请给我一个解决方案。也欢迎任何推荐。

谢谢

4

15 回答 15

44

设置setOnPageChangeListener为您的ViewPager

保持一个全局变量为

private int lastPosition = 0;

并且在

@Override
public void onPageSelected(int arg0) {
    if (lastPosition > position) {
         System.out.println("Left");
      }else if (lastPosition < position) {
         System.out.println("Right");
      }
      lastPosition = position;
}
于 2012-12-02T08:05:51.903 回答
42

这不是一个完美的解决方案,但这里有一种方法可以在您开始滑动时检查滑动方向:

new ViewPager.OnPageChangeListener() {

            private static final float thresholdOffset = 0.5f;
            private boolean scrollStarted, checkDirection;

            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                if (checkDirection) {
                    if (thresholdOffset > positionOffset) {
                        Log.i(C.TAG, "going left");
                    } else {
                        Log.i(C.TAG, "going right");
                    }
                    checkDirection = false;
                }
            }

            @Override
            public void onPageSelected(int position) {}

            @Override
            public void onPageScrollStateChanged(int state) {
                if (!scrollStarted && state == ViewPager.SCROLL_STATE_DRAGGING) {
                    scrollStarted = true;
                    checkDirection = true;
                } else {
                    scrollStarted = false;
                }
            }
        });


编辑:有一种更优雅的方法涉及使用 aViewPager.PageTransformer并检查它的位置间隔:

...
myViewPager.setPageTransformer(true, new PageTransformer());
...

public class PageTransformer implements ViewPager.PageTransformer {
    public void transformPage(View view, float position) {

        if (position < -1) { 
            // [-00,-1): the page is way off-screen to the left.
        } else if (position <= 1) { 
            // [-1,1]: the page is "centered"
        } else { 
            // (1,+00]: the page is way off-screen to the right.           
        }
    }
}

您可以从以下内容了解更多信息:将 ViewPager 用于屏幕幻灯片

于 2014-10-31T14:42:01.917 回答
21
  1. 这是我在 ViewPager.OnPageChangeListener 的onPageScrolled ()方法中的简单解决方案:

在此处输入图像描述

于 2015-12-18T13:10:05.910 回答
6

与 GuilhE 相同的解决方案,但有一个小修复,以避免在 ViewPager 中的第一页(没有更多页面向左)上向左翻页(向右滑动)时出现误报。它只是做一个额外的检查,看看滑动是否真的移动了。

new ViewPager.OnPageChangeListener() {

  private static final float thresholdOffset = 0.5f;
  private static final int thresholdOffsetPixels = 1;
  private boolean scrollStarted, checkDirection;

  @Override
  public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
    if (checkDirection) {
      if (thresholdOffset > positionOffset && positionOffsetPixels > thresholdOffsetPixels) {
        Log.i(C.TAG, "going left");
      } else {
        Log.i(C.TAG, "going right");
      }
    checkDirection = false;
  }
}

  @Override
  public void onPageSelected(int position) {}

  @Override
  public void onPageScrollStateChanged(int state) {
    if (!scrollStarted && state == ViewPager.SCROLL_STATE_DRAGGING) {
      scrollStarted = true;
      checkDirection = true;
    } else {
      scrollStarted = false;
    }
  }
 });
于 2016-02-18T19:06:00.753 回答
3

您可以保留类成员变量以保存上次访问的页面

private int mLastVisitedPageIndex = 0;

然后使用以下功能检查方向

@Override
public void onPageSelected(int i) {
    boolean isMovingForward = mLastVisitedPageIndex < i?true:false;
    //Use isMovingForward variable anywhere now
    mLastVisitedPageIndex = i;
}
于 2014-10-16T06:39:33.537 回答
3

用那个

@Override
public void onPageSelected( int position )
{
    mCurrentFragmentPosition = position;
}
@Override
public void onPageScrolled( int position, float positionOffset, int positionOffsetPixels )
{
    boolean isGoingToRightPage = position == mCurrentFragmentPosition;
    if(isGoingToRightPage)
    {
        // user is going to the right page
    }
    else
    {
        // user is going to the left page
    }
}
于 2014-11-07T22:01:02.487 回答
2

使用ViewPager.OnPageChangeListener界面。您可以使用传递给的位置参数onPageSelected并将其与先前的值进行比较,以确定ViewPager滚动的方式。

于 2012-12-02T08:03:04.813 回答
2
private float sumPositionAndPositionOffset;

@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
    boolean isSwipeToLeft = position + positionOffset > sumPositionAndPositionOffset;
    sumPositionAndPositionOffset = position + positionOffset;   
}
于 2017-03-22T12:34:57.680 回答
1

我用这个实现解决了这个问题。希望能帮助到你。

public static final float EPSILON= 0.001f;

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

    // initial position (positionOffset == 0)
    if (positionOffset < EPSILON) {
        mIsRight = positionOffset < 0.5;
        return;
    }

    // code here
    if (mIsRight) {
    } else {
    }
}
于 2015-10-19T10:34:30.377 回答
1

我们也可以使用自定义 Viewpager 来做到这一点,它可以包含 swipeLeft() 和 swipeRight() 方法,并且它的 onTouchEvent(MotionEvent event) 方法可以包含 ACTION_MOVE 和 ACTION_CANCEL 情况。

// 如果有帮助,这可以是代码。

public class SwiperViewPager extends ViewPager {

    SwiperListener mSwiperListener;
    private float downX;
    private float downY;
    private boolean isTouchCaptured;
    private float upX1;
    private float upY1;
    private float upX2;
    private float upY2;

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

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

    private float x1, x2;
    static final int min_distance = 20;

    boolean eventSent = false;

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_MOVE: {
                downX = event.getX();
                downY = event.getY();

                if (!isTouchCaptured) {
                    upX1 = event.getX();
                    upY1 = event.getY();
                    isTouchCaptured = true;
                } else {
                    upX2 = event.getX();
                    upY2 = event.getY();
                    float deltaX = upX1 - upX2;
                    float deltaY = upY1 - upY2;
                    //HORIZONTAL SCROLL
                    if (Math.abs(deltaX) > Math.abs(deltaY)) {
                        if (Math.abs(deltaX) > min_distance) {
                            // left or right
                            if (deltaX < 0) {
                                if(!eventSent && mSwiperListener!=null){
                                    mSwiperListener.onLeftSwipe();
                                    eventSent = true;
                                }
                            }
                            if (deltaX > 0) {
                                if(!eventSent && mSwiperListener!=null){
                                    if(mSwiperListener.onRightSwipe()){
                                        eventSent = true;
                                        return false;
                                    }
                                }
                            }
                        } else {
                            //not long enough swipe...
                        }
                    }
                    //VERTICAL SCROLL
                    else {
                        if (Math.abs(deltaY) > min_distance) {
                            // top or down
                            if (deltaY < 0) {

                            }
                            if (deltaY > 0) {

                            }
                        } else {
                            //not long enough swipe...
                        }
                    }
                }
            }
            break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:{
                isTouchCaptured = false;
                eventSent = false;
            }

        }
        return super.onTouchEvent(event);
    }

    public void setmSwiperListener(SwiperListener mSwiperListener) {
        this.mSwiperListener = mSwiperListener;
    }

    public static interface SwiperListener {
        public boolean onLeftSwipe();

        public boolean onRightSwipe();
    }

}
于 2016-04-21T09:31:03.207 回答
1

道歉 - 因为我发现了一个错误,所以不得不编辑答案。这是改进的解决方案:

该解决方案将当前页面索引与先前选择的页面索引 (previousPageIndex) 进行比较

newPageIndex 表示即将滚动到的页面。

Condition (positionOffset == 0) 比较滚动是否完成

private int previousPageIndex = 0;
private int newPageIndex = -1;

private final int MOVE_DIRECTION_NONE = 0;
private final int MOVE_DIRECTION_LEFT = 1;
private final int MOVE_DIRECTION_RIGHT = 2;

private int moveDirection = MOVE_DIRECTION_NONE;


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

    if (moveDirection == MOVE_DIRECTION_NONE) {
        if (previousPageIndex  == position){
            moveDirection = MOVE_DIRECTION_LEFT;
            if (newPageIndex == -1) newPageIndex = previousPageIndex + 1;
        }  else {
            moveDirection = MOVE_DIRECTION_RIGHT;
            if (newPageIndex == -1) newPageIndex = previousPageIndex - 1;
        }
    }

    if (positionOffset == 0) {
        System.out.println("Reseting");
        previousPageIndex = position;
        moveDirection = MOVE_DIRECTION_NONE;
        newPageIndex = -1;
    }

    switch (moveDirection) {
        case MOVE_DIRECTION_LEFT:
            if (onPageChangingHandler != null) onPageChangingHandler.pageChanging(previousPageIndex, newPageIndex, positionOffset);
            System.out.println("Sliding Left | Previous index: " + previousPageIndex + " | New Index: " + newPageIndex + " | offset: " + positionOffset  + " | Position: " + position);
            break;
        case MOVE_DIRECTION_RIGHT:
            if (onPageChangingHandler != null) onPageChangingHandler.pageChanging(newPageIndex, previousPageIndex, positionOffset);
            System.out.println("Sliding Right | Previous index: " + previousPageIndex + " | New Index: " + newPageIndex + " | offset: " + positionOffset + " | Position: " + position);
            break;
        case MOVE_DIRECTION_NONE:
            System.out.println("Moving NONE");
            break;
    }
}
于 2020-08-20T08:28:34.050 回答
0
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {

        private int mCurrentSelectedScreen;
        private int mNextSelectedScreen;
        private static final float thresholdOffset = 0.5f;
        private boolean scrollStarted=true, checkDirection=false;
        ArrayList<Integer> comp_ary=new ArrayList<Integer>();

        @Override
        public void onPageSelected(int arg0) {
        }

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

        //Log.e("positionOffsetPixels : "+positionOffsetPixels, "positionOffset : "+positionOffset);
        comp_ary.add(positionOffsetPixels);
             if (checkDirection) {
                    if (comp_ary.get(2) < comp_ary.get(comp_ary.size()-1)) {

                        Log.e("going left", "going left");
                    } else
                        if (comp_ary.get(2) > comp_ary.get(comp_ary.size()-1))
                    {

                        Log.e("going right", "going right");
                    }
                    checkDirection = false;
                    comp_ary=new ArrayList<Integer>();
                }
        }

        @Override
        public void onPageScrollStateChanged(int arg0) {




            if (!scrollStarted && arg0 == ViewPager.SCROLL_STATE_SETTLING) {
                scrollStarted = true;
                checkDirection = true;
            } else {
                scrollStarted = false;
            }


        }
    });
于 2014-11-26T08:08:14.087 回答
0

如果您担心位置偏移0取值后0.9F

    private boolean LEFT_DAB; //left swipe
    private float offset; //current position offset
    private float take_off; //previous position offset
    private static final float quavo = 0.5F; //position offset threshold

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

        offset = take_off > 0.9F ? take_off : positionOffset;
        take_off = positionOffset;

        if (offset > quavo) {
            LEFT_DAB = false;//RIGHT_SWIPE
        } else {
            LEFT_DAB = true;//LEFT_SWIPE
        }
    }
于 2021-01-24T11:50:47.460 回答
0

这是一种在滚动方向发生时可以知道滚动方向的方法。您所要做的就是OnPageChangeCallback()ViewPager. ViewPager您保存in的当前页面OnPageSelected()并将其与 的position参数进行比较OnPageScrolled()。如果当前页面小于或等于 ,position则向右滚动,否则,向左滚动。

var currentPage = 0
viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
    override fun onPageSelected(position: Int) {
        super.onPageSelected(position)
        currentPage = position
    }

    override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
        super.onPageScrolled(position, positionOffset, positionOffsetPixels)
        if (currentPage <= position) {
            // We are scrolling right
        } else {
            // We are scrolling left
        }
    }
})
于 2021-03-03T02:54:05.513 回答
-1
pager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            if(position  == pager.getCurrentItem()){
                // Move Right
            }
            else{
                // Move Left
            }

        }
于 2015-08-21T08:40:56.390 回答