Android觸摸事件的分發(fā)機制

參與分發(fā)的組件


  • Activity
    無onInterceptTouchEvent方法,不進行攔截,直接傳遞給子view

dispatchTouchEvent
onTouchEvent

  • ViewGroup

dispatchTouchEvent
onInterceptTouchEvent
onTouchEvent

  • View
    無onInterceptTouchEvent方法,dispatchTouchEvent返回默認時直接傳遞給onTouchEvent

dispatchTouchEvent
onTouchEvent

參與事件分發(fā)的方法


dispatchTouchEvent

  1. 返回值為默認值,有下列3種情況
 @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        return super.dispatchTouchEvent(ev);
    }

Activity
無onInterceptTouchEvent,直接傳遞給子View
ViewGroup
調用自身onInterceptTouchEvent方法,并決定下一步事件傳遞
View
無onInterceptTouchEvent,直接調用自身onTouchEvent

  1. 返回值為true
 @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        return true;
    }

終結傳遞,即常用術語(消費)
事件不再向下傳遞,傳遞終止,并且后續(xù)事件同樣傳遞至此為止

  1. 返回值為false
 @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        return false;
    }

傳遞至父view的onTouchEvent
后續(xù)事件不再經過此view的dispatchTouchEvent方法

  1. 調用了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類進行手勢識別
  1. 為View或者Activity實現OnGestureListener接口,覆寫需要的手勢的回調方法。
  2. 創(chuàng)建一個GestureDetector對象mygesturedetector,設置其監(jiān)聽器。
  3. 覆寫View或者Activity的OnTouchEvent方法,調用或返回mygesturedetector.onTouchEvent(ev),將事件交給mygesturedetector處理。
  • 在ScrollView內重寫方法時,務必調用super.dispatchTouchEvent(ev),否則自帶慣性滑動將會失效

參考:
Android中Touch事件傳遞總結
圖解 Android 事件分發(fā)機制

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容