34

我正在使用由 6 个页面组成的 ViewPager 来显示一些数据。我希望能够在用户位于位置 0 并尝试向右滑动(向后)或在位置 5 并尝试向左滑动(向前)时调用方法,即使这些页面不存在方向。有什么办法可以听这些场景吗?

4

5 回答 5

51

扩展 ViewPager 并onInterceptTouchEvent()像这样覆盖:

public class CustomViewPager extends ViewPager {

    float mStartDragX;
    OnSwipeOutListener mListener;


    public void setOnSwipeOutListener(OnSwipeOutListener listener) {
        mListener = listener;
    }


    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        float x = ev.getX();
        switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN:
            mStartDragX = x;
            break;
        case MotionEvent.ACTION_MOVE:
            if (mStartDragX < x && getCurrentItem() == 0) {
                mListener.onSwipeOutAtStart();
            } else if (mStartDragX > x && getCurrentItem() == getAdapter().getCount() - 1) {
                mListener.onSwipeOutAtEnd();
            }
            break;
        }
        return super.onInterceptTouchEvent(ev);
    }

    public interface OnSwipeOutListener {
        public void onSwipeOutAtStart();
        public void onSwipeOutAtEnd();
    }

}
于 2012-11-12T15:59:36.717 回答
17

Flávio Faria 的回答对我不起作用。我在 onInterceptTouchEvent() 中得到的唯一事件是 ACTION_DOWN 事件。所以我重写了 onTouchEvent() 方法来让它工作。

这是代码。请注意,我在侦听器中只有 onSwipeOutAtEnd() 。您可以添加代码以支持在第一个 vier 上向左滑动。

public class CustomViewPager extends ViewPager {

float mStartDragX;
OnSwipeOutListener mListener;


public void setOnSwipeOutListener(OnSwipeOutListener listener) {
    mListener = listener;
}

@Override
public boolean onTouchEvent(MotionEvent ev){
    if(getCurrentItem()==getAdapter().getCount()-1){
        final int action = ev.getAction();
        float x = ev.getX();
        switch(action & MotionEventCompat.ACTION_MASK){
        case MotionEvent.ACTION_DOWN:
            mStartDragX = x;
            break;
        case MotionEvent.ACTION_MOVE:
            break;
        case MotionEvent.ACTION_UP:
            if (x<mStartDragX){
                mListener.onSwipeOutAtEnd();
            }else{
                mStartDragX = 0;
            }
            break;
        }
    }else{
        mStartDragX=0;
    }
    return super.onTouchEvent(ev);
}    
public interface OnSwipeOutListener {
    public void onSwipeOutAtEnd();
}
于 2013-06-07T20:52:05.967 回答
17

非常感谢@Flavio,虽然我不得不对他的代码进行一些更改,因为回调方法被触发了两次,我还添加了代码来检查是否有任何注册的监听器,以避免在没有注册监听器时应用程序崩溃。这是我用来使它工作的代码,包括 onSwipeOutAtStart 和 onSwipeOutAtEnd:

public class CustomViewPager extends android.support.v4.view.ViewPager {

    float mStartDragX;
    OnSwipeOutListener mOnSwipeOutListener;

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

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

    public void setOnSwipeOutListener(OnSwipeOutListener listener) {
        mOnSwipeOutListener = listener;
    }

    private void onSwipeOutAtStart() {
        if (mOnSwipeOutListener!=null) {
            mOnSwipeOutListener.onSwipeOutAtStart();
        }
    }

    private void onSwipeOutAtEnd() {
        if (mOnSwipeOutListener!=null) {
            mOnSwipeOutListener.onSwipeOutAtEnd();
        }
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        switch(ev.getAction() & MotionEventCompat.ACTION_MASK){
            case MotionEvent.ACTION_DOWN:
                mStartDragX = ev.getX();
                break;
        }
        return super.onInterceptTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev){

        if(getCurrentItem()==0 || getCurrentItem()==getAdapter().getCount()-1){
            final int action = ev.getAction();
            float x = ev.getX();
            switch(action & MotionEventCompat.ACTION_MASK){
                case MotionEvent.ACTION_MOVE:
                    break;
                case MotionEvent.ACTION_UP:
                    if (getCurrentItem()==0 && x>mStartDragX) {
                        onSwipeOutAtStart();
                    }
                    if (getCurrentItem()==getAdapter().getCount()-1 && x<mStartDragX){
                        onSwipeOutAtEnd();
                    }
                    break;
            }
        }else{
            mStartDragX=0;
        }
        return super.onTouchEvent(ev);

    }

    public interface OnSwipeOutListener {
        void onSwipeOutAtStart();
        void onSwipeOutAtEnd();
    }
}
于 2015-06-12T22:24:48.850 回答
16

在 ViewPager 上设置OnPageChangeListener怎么样?然后您可以修改导航箭头或 onPageScrolled 中的任何内容。

viewPager.setOnPageChangeListener(new OnPageChangeListener() {
    @Override
    public void onPageSelected(int position) {
    }

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

    @Override
    public void onPageScrollStateChanged(int state) {
    }
});
于 2013-06-04T10:18:32.993 回答
4

我想知道它对其他人如何起作用,它对我不起作用。

onInterceptTouchEvent()只需要ACTION_DOWN事件。虽然onTouchEvent()一次只接受一个事件,但ACTION_DOWN其他事件ACTION_UP

我必须覆盖两者onInterceptTouchEvent()onTouchEvent()使其正常工作。的抓取初始点,并ACTION_DOWN抓取最终点。我比较了它来检测滑动方向。onInterceptTouchEventXOnTouchEventX2

获取触摸的初始 X 值:

float x1 = 0;
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
        switch(ev.getAction() & MotionEventCompat.ACTION_MASK){
        case MotionEvent.ACTION_DOWN:
            x1 = ev.getX();
            break;
        }
        return super.onInterceptTouchEvent(ev);
    }

从 tjlian616 的代码中,onTouchEvent()监听ACTION_UP并获取它的最后一个X值。虽然我已将当前项目的值设置为 0 以在启动侦听器时滑出。比较它并添加激发了听众。

 @Override
 public boolean onTouchEvent(MotionEvent ev){
        if(getCurrentItem()==0){
            final int action = ev.getAction();
            switch(action & MotionEventCompat.ACTION_MASK){
            case MotionEvent.ACTION_MOVE:
                break;
            case MotionEvent.ACTION_UP:
                mStartDragX = ev.getX();
                if (x1<mStartDragX){
                    Log.i("TOUCH: ", "ACTION UP " + x1 + " : " + mStartDragX );
                    mListener.onSwipeOutAtStart();
                }else{
                    Log.i("TOUCH ELSE : ", "ACTION UP " + x1 + " : " + mStartDragX );
                    mStartDragX = 0;
                }
                break;
            }
        }else{
            mStartDragX=0;
        }
        return super.onTouchEvent(ev);
    }    
于 2014-09-04T03:40:24.920 回答