Android 解决 ViewPager OnTouchListener 方法监听无效

解决 ViewPager OnTouchListener 方法监听无效

        工作中在做首页轮播图时有一个需求, 当用户滑动轮播图时暂停自动轮播, 用户手指离开屏幕时重新开始自动轮播. 此时我想到了使用setOnTouchListener 方法设置一个监听在用户ACTION_DWONACTION_UP时, 停止和开始自动轮播, 但跑起来后发现onTouch方法压根没有执行. 测试后发现, 如果onTouch方法返回值return false, 则监听收不到事件, 如果onTouch方法返回true, 则ViewPager不能正常滑动.

        然后我突然想到addOnPageChangeListener方法,其中的onPageScrolled回调在viewPager滑动时可以通过参数positionOffset实时监听滑动距离:

     addOnPageChangeListener(new OnPageChangeListener() {
          @Override
          public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
              Log.i("DEFAULT","position:"+position+" positionOffset:"+positionOffset+" positionOffsetPixels:"+positionOffsetPixels);
          }
          @Override
          public void onPageSelected(int position) {
          }
          @Override
          public void onPageScrollStateChanged(int state) {
          }
      });

突发奇想打印Log看看:
setCurrentItem(1,false)执行时打印Log如下:
这里写图片描述
当”setCurrentItem(1,true)”或者手指向左滑动手指从按下到离开中间所经历的Log
Android 解决 ViewPager OnTouchListener 方法监听无效_第1张图片

        分析Log后, 发现在不考虑 setCurrentItem 方法执行的情况下, 当positionOffset为0时永远代表ACTION_UP事件, 当positionOffset不为0时, 除第一次非零数据是ACTION_DOWN事件外, 其余都是ACTION_MOVE事件, 当然拿不到点击位置, 这也是没有办法的事.

        于是我想到了继承ViewPager, 通过该监听事件, 模拟出onTouchListener监听.

        具体代码如下, 定义三个状态 up move down, 默认状态是up, 通过监听onPageScrolled方法, positionOffset 为0时改变状态为up, 非0时如果状态为up则改变为down, 如果状态为down则改变状态为move, 设置开关setCurrentItemNoAnimStart来防止setCurrentItem(1,false|true)导致误触发事件, 虽然最终结果接收到down 和 up事件时有迟缓并且得不到按下位置, 但能够得到 down up move 三种状态已经完美解决了轮播图的需求.

        希望这篇博文也能帮到正在看的你.

补充: 最近看了一些博客, 找到一种更好的方案解决 ViewPager监听问题, 做法是重写 viewPager dispatchTouchEvent 方法, 在该方法里写一个监听事件, 简单高效, 能更快更准确的获取到监听, 不得不承认比我的方法好.

// 大神的方案...
public class SuperViewPager extends ViewPager{
    public static final int STATE_DOWN = MotionEvent.ACTION_DOWN;
    public static final int STATE_UP = MotionEvent.ACTION_UP;
    public static final int STATE_MOVE = MotionEvent.ACTION_MOVE;

    int state = STATE_UP;

    public SuperViewPager(Context context) {
        super(context);

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

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if(mOnTouchListener != null)
            mOnTouchListener.onTouch(ev.getAction());
        return super.dispatchTouchEvent(ev);
    }

    public void setOnTouchListener(OnTouchListener l) {
        mOnTouchListener = l;
    }

    OnTouchListener mOnTouchListener;

    interface OnTouchListener {
        void onTouch(int state);
    }
}
// 我的方案
public class SuperViewPager extends ViewPager{
    public static final int STATE_DOWN = 0;
    public static final int STATE_UP = 1;
    public static final int STATE_MOVE = -1;

    int state = STATE_UP;

    boolean setCurrentItemNoAnimStart;

    private OnPageChangeListener mOnPageChangeListener = new OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            //Log.i(Util.getTag(null),"position:"+position+" positionOffset:"+positionOffset+" positionOffsetPixels:"+positionOffsetPixels);
//... 相当于 viewpager onTouchListener
            if(positionOffset == 0){
//                Log.i(Util.getTag(null),"HAHA_position:"+position);
                if(setCurrentItemNoAnimStart){
                    setCurrentItemNoAnimStart = false;
                }else {
                    state = STATE_UP;
                    if (mOnTouchListener != null)
                        mOnTouchListener.onTouch(STATE_UP);
                }
            }else{
                if(!setCurrentItemNoAnimStart){
                    if (state == STATE_UP) {
                        state = STATE_DOWN;
                        if (mOnTouchListener != null)
                            mOnTouchListener.onTouch(STATE_DOWN);
                    } else if(state == STATE_DOWN) {
                        state = STATE_MOVE;
                        if (mOnTouchListener != null)
                            mOnTouchListener.onTouch(STATE_MOVE);
                    }
                }
            }
            //...
        }

        @Override
        public void onPageSelected(int position) {
        }

        @Override
        public void onPageScrollStateChanged(int state) {
        }
    };
    public SuperViewPager(Context context) {
        super(context);
    }

    public SuperViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
        addOnPageChangeListener(mOnPageChangeListener);
    }

    @Override
    public void setCurrentItem(int item, boolean smoothScroll) {
        if(!smoothScroll)
            setCurrentItemNoAnimStart = true;
        super.setCurrentItem(item, smoothScroll);
    }

    public void setOnTouchListener(OnTouchListener l) {
        mOnTouchListener = l;
    }
    OnTouchListener mOnTouchListener;

    interface OnTouchListener {
        void onTouch(int state);
    }
}

你可能感兴趣的:(Android)