一个最简单的屏幕触摸动作触发了一系列Touch事件:ACTION_DOWN->ACTION_MOVE->ACTION_MOVE->ACTION_MOVE...->ACTION_MOVE->ACTION_UP
当 屏幕中包含一个ViewGroup,而这个ViewGroup又包含一个子view,这个时候android系统如何处理Touch事件呢?到底是 ViewGroup来处理Touch事件,还是子view来处理Touch事件呢?我只能很肯定的对你说不一定。呵呵,为什么呢?看看下面我的调查结果你 就明白了。
android系统中的每个View的子类都具有下面三个和TouchEvent处理密切相关的方法:
1)public boolean dispatchTouchEvent(MotionEvent ev)
2)public boolean onInterceptTouchEvent(MotionEvent ev) 这个方法用来拦截TouchEvent
3)public boolean onTouchEvent(MotionEvent ev) 这个方法用来处理TouchEvent
当 TouchEvent发生时,首先Activity将TouchEvent传递给最顶层的View, TouchEvent最先到达最顶层 view 的 dispatchTouchEvent ,然后由
让子先处理的方法是 从写父的onInterceptTouchEvent事件并返回false
public boolean onInterceptTouchEvent(MotionEvent ev) {
所以,如果我们最外面是一个ScrollView,里面又有一个Viewpager或者水平滑动的广告,这个时候默认他们就会产生冲突,当你在子View上水平滑动,如果不是非常标准的水平滑动,就会使外面的ScrollView垂直滑动,或者有跳动的感觉,这些都是滑动冲突导致的,那怎么解决呢?
按照上面的思路,最外面的ScrollView首先会接收到滑动事件,如果对这个滑动进行判断,如果是水平的话,就把这个滑动事件返回给自己的子View来出来,只有垂直滑动才给自己的onTouchEvent来处理即可,所以我们需要重写ScrollView的onInterceptTouchEvent方法,代码如下:
/**
* 能够兼容ViewPager的ScrollView
* @Description: 解决了ViewPager在ScrollView中的滑动反弹问题
*/
public class ScrollViewExtend extends ScrollView {
// 滑动距离及坐标
private float xDistance, yDistance, xLast, yLast;
public ScrollViewExtend(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
xDistance = yDistance = 0f;
xLast = ev.getX();
yLast = ev.getY();
break;
case MotionEvent.ACTION_MOVE:
final float curX = ev.getX();
final float curY = ev.getY();
xDistance += Math.abs(curX - xLast);
yDistance += Math.abs(curY - yLast);
xLast = curX;
yLast = curY;
if(xDistance > yDistance){
return false;
}
}
return super.onInterceptTouchEvent(ev);
}
}
本文参考:
http://blog.sina.com.cn/s/blog_9bb108790101aydx.html
http://glblong.blog.51cto.com/3058613/1307717