ViewPager 的点击监听与存在的误触问题

in 在路上

ViewPager 是不自带 onItemClickListener 之类的方法的,解决方案也很简单,就是在 PagerAdapter 的 instantiateItem 方法里为每个页面加上监听。这是业界通常的做法,但是为毛没一个人提到这样会产生误触问题呢Orz……虽然解决误触也不复杂啦,但是我还是纳闷为啥我之前搜都没有相关资料呢……所以我还是写下这篇帮助下会被此困扰的人吧。

ViewPager 的点击事件监听

public class StartViewPagerAdapter extends PagerAdapter {
    private List mListViews;
    private View.OnClickListener clickListener;

    public StartViewPagerAdapter(List mListViews,View.OnClickListener clickListener) {
        this.mListViews = mListViews;
        this.clickListener=clickListener;
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {  
        container.addView(mListViews.get(position), 0);
        mListViews.get(position).setOnClickListener(clickListener);
        //TODO 后面解决误触的代码
        return mListViews.get(position);
    }
}

然后创建的时候把 clickListener 传进来就行,没啥好说的。

ViewPager 点击误触的表现

横向滑动正常,竖着滑动则必然会触发点击事件,斜着滑动在一定角度下也会触发点击事件。

 

解决方案

当然是加一个 OnTouchListener 就好了啊。你需要掌握的前置知识是『Android 的事件传递机制』,推荐去看郭霖大触的Android事件分发机制完全解析,带你从源码的角度彻底理解。看完后反正你知道在 OnTouchListener 的 onTouch 方法里 return true 就可以把点击事件拦截了。

然后代码如下(写在 PagerAdapter 的 instantiateItem 里):

mListViews.get(position).setOnTouchListener(new View.OnTouchListener() {
    private float startY;
    private float startX;

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                startX=event.getX();
                startY=event.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                break;
            case MotionEvent.ACTION_UP:
                float currentX=event.getX();
                float currentY=event.getY();
                float height=Math.abs(currentY-startY);
                float width=Math.abs(currentX-startX);
                if (width/height>2&&height>10){
                    //Xlog.log("拦截点击事件");
                    return true;
                }
                break;
        }
        return false;
    }
});

『width/height<2』是根据轨迹的斜率来判断是否左右滑动的,假如觉得还有误触这个值可以更大一点,『height>10』是当偏移量大于10的时候才可能拦截,不然会影响正常点击操作了。

没啥难点,就这样吧。

标签:, , , ,
© 2018 一隅 - Powered by Wordpress / Theme: Tabinikki