參與分發(fā)的組件
- Activity
無onInterceptTouchEvent方法,不進行攔截,直接傳遞給子view
dispatchTouchEvent
onTouchEvent
- ViewGroup
dispatchTouchEvent
onInterceptTouchEvent
onTouchEvent
- View
無onInterceptTouchEvent方法,dispatchTouchEvent返回默認時直接傳遞給onTouchEvent
dispatchTouchEvent
onTouchEvent
參與事件分發(fā)的方法
dispatchTouchEvent
- 返回值為默認值,有下列3種情況
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
return super.dispatchTouchEvent(ev);
}
Activity
無onInterceptTouchEvent,直接傳遞給子View
ViewGroup
調用自身onInterceptTouchEvent方法,并決定下一步事件傳遞
View
無onInterceptTouchEvent,直接調用自身onTouchEvent
- 返回值為true
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
return true;
}
終結傳遞,即常用術語(消費)
事件不再向下傳遞,傳遞終止,并且后續(xù)事件同樣傳遞至此為止
- 返回值為false
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
return false;
}
傳遞至父view的onTouchEvent
后續(xù)事件不再經過此view的dispatchTouchEvent方法
- 調用了super.dispatchTouchEvent(ev)
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
super.dispatchTouchEvent(ev);
return true/false;
}
只要調用了super.dispatchTouchEvent(ev),就一定會進行下一步傳遞
返回值為true,后續(xù)繼續(xù)接收事件
返回值為false,不再接收后續(xù)事件
總結
dispatchTouchEvent可以理解為事件分發(fā)的方法,其返回值決定了后續(xù)事件的接收,是否調用super.dispatchTouchEvent(ev)方法決定了此次事件是否繼續(xù)分發(fā)。
onInterceptTouchEvent
public boolean onInterceptTouchEvent(MotionEvent ev) {
return false;
}
此方法為事件攔截方法,方法默認返回false
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return super.onInterceptTouchEvent(ev);
}
返回值為super.onInterceptTouchEvent(ev)或false時,表示不進行攔截,事件會繼續(xù)傳遞至子view的dispatchTouchEvent方法。
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return true;
}
返回值為true時,表示攔截事件,直接把事件傳遞至當前view的onTouchEvent方法,并且后續(xù)事件經由當前view的dispatchTouchEvent傳遞至onTouchEvent,不再向下傳遞且不經過onInterceptTouchEvent
onTouchEvent
@Override
public boolean onTouchEvent(MotionEvent event) {
return super.onTouchEvent(event);
}
返回值super.onTouchEvent(event)或true時,消費事件,并且后續(xù)的MOVE UP事件會被此view攔截并傳遞至onTouchEvent。
如果處理MOVE事件時返回值為false,且父view沒有進行消費,后續(xù)的事件仍然會發(fā)送至此view處理。
如果如果處理MOVE事件時返回值為false,且父view消費,此view會獲取到CANCEL并且后續(xù)事件會發(fā)送至父VIEW。
@Override
public boolean onTouchEvent(MotionEvent event) {
return false;
}
返回值為false時,傳遞至父view的onTouchEvent。
流程
默認流程
dispatchTouchEvent(Activity)----->dispatchTouchEvent(ViewGroup)----->onInterceptTouchEvent(ViewGroup)----->dispatchTouchEvent(View)----->onTouchEvent(View)----->onTouchEvent(ViewGroup)----->onTouchEvent(Activity)
onTouchEvent(ViewGroup)消費事件,后續(xù)流程
dispatchTouchEvent(Activity)----->dispatchTouchEvent(ViewGroup)----->onInterceptTouchEvent(ViewGroup)----->dispatchTouchEvent(View)----->onTouchEvent(View)----->onTouchEvent(ViewGroup)
dispatchTouchEvent(ViewGroup)消費事件,后續(xù)流程
dispatchTouchEvent(Activity)----->dispatchTouchEvent(ViewGroup)----->onInterceptTouchEvent(ViewGroup)----->dispatchTouchEvent(View)
TIPS
- 如果我們在一個View中同時覆寫了onClick、onLongClick及onTouchEvent的話,onTouchEvent是最先捕捉到ACTION_DOWN和ACTION_UP事件的,其次才可能觸發(fā)onClick或者onLongClick
- onTouchListener的onTouch方法優(yōu)先級比onTouchEvent高,會先觸發(fā)。假若onTouchListener中的onTouch方法返回true,表示此次事件已經被消費了,那onTouchEvent是接收不到消息的。假如onTouch方法返回false,會接著觸發(fā)onTouchEvent,反之onTouchEvent方法不會被調用。內置諸如click事件的實現等等都基于onTouchEvent,假如onTouch返回true,這些事件將不會被觸發(fā)。
- GestureDetector類進行手勢識別
- 為View或者Activity實現OnGestureListener接口,覆寫需要的手勢的回調方法。
- 創(chuàng)建一個GestureDetector對象mygesturedetector,設置其監(jiān)聽器。
- 覆寫View或者Activity的OnTouchEvent方法,調用或返回mygesturedetector.onTouchEvent(ev),將事件交給mygesturedetector處理。
- 在ScrollView內重寫方法時,務必調用super.dispatchTouchEvent(ev),否則自帶慣性滑動將會失效