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