Android 事件分發機制詳解

View 中的dispatchTouchEvent,OnInterceptTouchEvent ,OnTouchEvent方法 這篇文章中介紹了一下dispatchTouchEvent,OnInterceptTouchEvent ,OnTouchEvent三個方法。今天想分析一下觸摸事件分發和處理機制。
  爲了能夠清楚的分析,我們先新建一個項目,佈局如圖:
  這裏寫圖片描述
  ViewGroup1嵌套ViewGroup2,然後在嵌套CustomView(這裏我繼承自TextView)。佈局很簡單,只是爲了說明ViewGroup的分發過程。
  然後在相應的View中重寫dispatchTouchEvent,OnInterceptTouchEvent ,OnTouchEvent方法(CustomView沒有OnInterceptTouchEvent),並在每個方法中輸出相應的Log:
  

 @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        Log.e("ViewGroup1","ViewGroup1 dispatchTouchEvent");
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        Log.e("ViewGroup1","ViewGroup1 onInterceptTouchEvent");
        return super.onInterceptTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.e("ViewGroup1","ViewGroup1 onTouchEvent");
        return super.onTouchEvent(event);
    }

CustomView中:

 @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        Log.e("CustomView", "CustomView dispatchTouchEvent");
        return super.dispatchTouchEvent(event);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.e("CustomView", "CustomView onTouchEvent");
        return super.onTouchEvent(event);
    }

  運行程序,點擊CustomView會得到如下Log信息:
  

 E/ViewGroup1: ViewGroup1 dispatchTouchEvent
 E/ViewGroup1: ViewGroup1 onInterceptTouchEvent
 E/ViewGroup2: ViewGroup2 dispatchTouchEvent
 E/ViewGroup2: ViewGroup2 onInterceptTouchEvent
 E/CustomView: CustomView dispatchTouchEvent
 E/CustomView: CustomView onTouchEvent
 E/ViewGroup2: ViewGroup2 onTouchEvent
 E/ViewGroup1: ViewGroup1 onTouchEvent

  從Log信息可以看出,首先會先執行ViewGroup1 dispatchTouchEvent方法,然後在View 中的dispatchTouchEvent,OnInterceptTouchEvent ,OnTouchEvent方法 中我們講過dispatchTouchEvent()方法的內部邏輯:
  

public boolean dispatchTouchEvent(Motion e){
     boolean result=false;
     if(onInterceptTouchEvent(e)){
     //如果當前View截獲事件,那麼事件就會由當前View處理,即調用onTouchEvent()
        result=onTouchEvent(e);
     }else{
        //如果不截獲那麼交給其子View來分發
        result=child.dispatchTouchEvent(e);
     }
     return result;
}

  在ViewGroup1 dispatchTouchEvent方法調用後,接着會調用onInterceptTouchEvent()來判斷是否需要截取事件,默認是不截取的。事件會傳遞到ViewGroup1的子View也就是ViewGroup2。即ViewGroup2 的dispatchTouchEvent方法被調用,直到CustomView。當事件傳遞到CustomView後,同樣是CustomView的dispatchTouchEvent方法會執行。可以看出,整個事件的分發是從ViewGroup1向CustomView傳遞的。此時如果CustomView 不能處理改事件,也就是說CustomView的OnTouchView方法返回爲false,那麼事件會向上交給ViewGroup2的OnTouchEvent()事件處理,以此類推:
  這裏寫圖片描述
  如果ViewGroup2的onInterceptTouchEvent()返回爲true,即要攔截事件,又會出現什麼情況呢?
  

 @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        Log.e("ViewGroup2","ViewGroup2 onInterceptTouchEvent");
        return true;
    }

運行結果:

E/ViewGroup1: ViewGroup1 dispatchTouchEvent
E/ViewGroup1: ViewGroup1 onInterceptTouchEvent
E/ViewGroup2: ViewGroup2 dispatchTouchEvent
E/ViewGroup2: ViewGroup2 onInterceptTouchEvent
E/ViewGroup2: ViewGroup2 onTouchEvent
E/ViewGroup1: ViewGroup1 onTouchEvent

  CustomView的dispatchTouchEvent()沒有執行,事件沒有傳遞給CustomView,而是直接調用了ViewGroup2的ViewGroup2 的onTouchEvent。
  這裏寫圖片描述
  其實這也是很好理解的,和我們日常生活中辦事流程是一樣的,公司老闆(ViewGroup1)把任務交給經理(ViewGroup2),經理在把工作交給員工(CustomView)。這裏如果經理(ViewGroup2)覺得這件事自己可以完成就截獲這個工作(onInterceptTouchEvent返回爲true),就不會再將任務分配給員工(CustomView)處理了。
  說完分發流程,現在來看看事件的響應機制,我們將事件傳遞到CustomView,並且將CustomView的OnTouchEvent事件返回爲true,得到以下結果:
  

E/ViewGroup1: ViewGroup1 dispatchTouchEvent
E/ViewGroup1: ViewGroup1 onInterceptTouchEvent
E/ViewGroup2: ViewGroup2 dispatchTouchEvent
E/ViewGroup2: ViewGroup2 onInterceptTouchEvent
E/CustomView: CustomView dispatchTouchEvent
E/CustomView: CustomView onTouchEvent

  我們會發現ViewGroup2 的OnTouchEvent不會在執行了,還是用我們剛剛的例子來說,就是員工(CustomView)在接到任務後順利的完成了任務,就不必在勞煩上司響應處理了。只有在員工(CustomView)無法完成這項工作時(OnTouchEvent返回爲false)時纔會請求經理幫忙(ViewGroup2 調用OnTouchEvent方法),同樣的,如果經理也不能搞定的話,就交給老闆了。
  如果有興趣的話,可以去研究研究源碼:
  推薦:
  Android事件分發機制完全解析,帶你從源碼的角度徹底理解(上)
  第21天 Android Touch事件學習 8 事件分發原理
  
  

發佈了42 篇原創文章 · 獲贊 19 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章