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的时候才可能拦截,不然会影响正常点击操作了。
没啥难点,就这样吧。