下面我們通過源碼來看看requestDisallowInterceptTouchEvent是怎麼起作用的。
requestDisallowInterceptTouchEvent函數實際上是ListView的父類AbsListView的一個函數,這個函數的源碼如下:
public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
if (disallowIntercept) {
recycleVelocityTracker();
}
super.requestDisallowInterceptTouchEvent(disallowIntercept);
}
可以看到是調用了父類的同名函數,即ViewGroup的requestDisallowInterceptTouchEvent函數,源碼如下:
public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
if (disallowIntercept == ((mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0)) {
// We're already in this state, assume our ancestors are too
return;
}
if (disallowIntercept) {
mGroupFlags |= FLAG_DISALLOW_INTERCEPT;
} else {
mGroupFlags &= ~FLAG_DISALLOW_INTERCEPT;
}
// Pass it up to our parent
if (mParent != null) {
mParent.requestDisallowInterceptTouchEvent(disallowIntercept);
}
}
其中mGroupFlags 保存的是二進制值,控制了幾個開關。
在這裏如果disallowIntercept爲true的話,則爲mGroupFlags添加FLAG_DISALLOW_INTERCEPT標誌。同時如果有父view,調用父view的同名函數。因爲父view也是ViewGroup,所以會一層層調用直到根佈局。
那麼FLAG_DISALLOW_INTERCEPT這個標誌是如何影響滑動事件的呢?
這個標誌使用在ViewGroup的dispatchTouchEvent函數中,由於代碼較多,我們只截取有關的部分,如下:
// 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;
}
當mGroupFlags有FLAG_DISALLOW_INTERCEPT這個標誌,則disallowIntercept爲true,這時intercepted爲false。
在dispatchTouchEvent函數的後續代碼中intercepted爲false則爲所有的子view分發touch事件。
回到之前的問題中,當listview或gridview的區域touch時,設置requestDisallowInterceptTouchEvent爲true,這樣scrollview的touch就會分發下去,這樣listview或gridview就可以響應滑動事件了。