requestDisallowInterceptTouchEvent方法是用来禁止或允许ViewGroup是否能拦截事件,通常用来处理滑动冲突.但如果在ViewGroup初始化之后立即就调用这个方法会发现这个方法并没有起到作用.
示例
class MyLayout extends LinearLayout {
public MyLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return true;
}
}
//主程序:
LinearLayout li = (LinearLayout) findViewById(R.id.li);
li.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.e(TAG, "click layout");
}
});
//不允许li拦截事件
li.requestDisallowInterceptTouchEvent(true);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.e(TAG, "click");
}
});
LinearLayout 的onInterceptTouchEvent已重写成返回true的形式
上面这段程序运行的结果是打印click layout,明明不允许拦截事件,为什么点击事件还是不能传递给button呢?翻看ViewGroup的dispatchTouchEvent方法源码发现了答案,源码中有这么一段:
boolean handled = false;
if (onFilterTouchEventForSecurity(ev)) {
final int action = ev.getAction();
final int actionMasked = action & MotionEvent.ACTION_MASK;
// Handle an initial down.
if (actionMasked == MotionEvent.ACTION_DOWN) {
// Throw away all previous state when starting a new touch gesture.
// The framework may have dropped the up or cancel event for the previous gesture
// due to an app switch, ANR, or some other state change.
cancelAndClearTouchTargets(ev);
resetTouchState();
}
// Check for interception.
final boolean intercepted;
if (actionMasked == MotionEvent.ACTION_DOWN
|| mFirstTouchTarget != null) {
final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
if (!disallowIntercept) {
intercepted = onInterceptTouchEvent(ev);
ev.setAction(action); // restore action in case it was changed
} else {
intercepted = false;
}
} else {
// There are no touch targets and this action is not an initial down
// so this view group continues to intercept touches.
intercepted = true;
}
在进行是否拦截之前,有一个判断,判断当前事件是否是 MotionEvent.ACTION_DOWN,如果是则调用resetTouchState方法,查看resetTouchState方法源码:
private void resetTouchState() {
clearTouchTargets();
resetCancelNextUpFlag(this);
mGroupFlags &= ~FLAG_DISALLOW_INTERCEPT;
}
原来在这个方法里面又重新允许拦截事件了,所以说我们自己代码里的请求根本就没用,默认情况下就是允许拦截的,正确使用requestDisallowInterceptTouchEvent是在一个事件系列中间使用。