引用: https://developer.android.com/training/gestures/viewgroup.html
对ViewGroup和它的子View来说,触摸事件的处理方式是不一样的。可以通过重载View Group的 onInterceptTouchEvent() 方法,来确保ViewGroup及各个子View能正确相应触摸事件。
ViewGroup拦截触摸事件
不管是触摸ViewGroup或它的子View,onInterceptTouchEvent()方法都会调用。该方法返回true, 则子View收不到Touch Event,执行ViewGroup的 onTouchEvent()。 如果返回false,则向子控件传递,调用相应的子View的 onTouchEvent()方法。
public class MyViewGroup extends ViewGroup {
private int mTouchSlop;
...
ViewConfiguration vc = ViewConfiguration.get(view.getContext());
mTouchSlop = vc.getScaledTouchSlop();
...
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
/*
* 此方法判断是否需要拦截触摸事件,如果是滑动操作,则返回true,运行本类的 onTouchEvent。
*/
final int action = MotionEventCompat.getActionMasked(ev);
// 先处理触摸完成的情况
if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
// Release the scroll.
mIsScrolling = false;
return false; // 不拦截Touch Event,让子View 处理
}
switch (action) {
case MotionEvent.ACTION_MOVE: {
if (mIsScrolling) {
// 如果正在滑动,则拦截Touch Event
return true;
}
// 判断手指横向移动超过一定距离,则开始滚动
// 需要读者自己实现 :)
final int xDiff = calculateDistanceX(ev);
// Touch slop should be calculated using ViewConfiguration
// constants.
if (xDiff > mTouchSlop) {
// 开始滚动!
mIsScrolling = true;
return true;
}
break;
}
...
}
// 通常情况下不拦截Touch Event,让子View来处理
return false;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
// 这里我们开始处理touch event (e.g. 如果action是ACTION_MOVE,滚动container)。intercepted in
// 这个方法只有在touch event在onInterceptTouchEvent中被截获时调用
...
}
}