onTouch 事件傳遞

夏雨友人帳發表於2017-04-11

前言

在我們的專案中,遇到比較複雜佈局的時候,最常見的就是佈局巢狀和自定義控制元件,那麼滑動衝突與點選衝突你一定是遇到過的,解決的方法有很多,但是總的來說都是對onTouch事件傳遞做處理.那麼我們就來了解一下onTouch事件到底是怎麼傳遞的

1.基本知識

我們先看看相關的幾個方法

(View是沒有onInterceptTouchEvent方法的)

ViewGroup

  • 1. dispatchTouchEvent(分發touch事件)
  • 2. onInterceptTouchEvent(攔截touch事件)
  • 3. onTouchEvent(消費事件)

View

  • 1. dispatchTouchEvent(分發touch事件)
  • 2. onTouchEvent(消費事件)

一個事件首先會由dispatchTouchEvent決定怎麼分配,接著由onInterceptTouchEvent決定是否攔截,最後由onTouchEvent決定怎麼消費

一般來說我們會重寫onInterceptTouchEvent和onTouchEvent方法來改變事件的傳遞,但是不會去重寫dispatchTouchEvent方法

下面為了更好的描述,有些地方就用簡稱描述了

  • dispatchTouchEvent : 分配
  • onInterceptTouchEvent : 攔截

2. 傳遞規律

(1)基本傳遞方向

首先我們需要知道onTouch事件傳遞的基本傳遞方向,onTouch事件的傳遞方向大概是從父控制元件傳遞到子控制元件,然後再從子控制元件傳回父控制元件,這個過程中一旦事件被消費了,那麼事件就不會繼續傳遞了

(2)攔截

onInterceptTouchEvent方法會有一個返回值,如果你返回的是false,表示不攔截,那麼事件就會先往子控制元件傳遞,如果你返回的是true,表示攔截,那麼事件不會往下傳遞了

(3)消費

可以消費事件的地方有兩個:

  • OnTouchListener: 通過setOnTouchListener設定的OnTouchListener裡面的onTouch方法
  • onTouchEvent: 控制元件本身的onTouchEvent方法

這兩個方法都有返回值,如果你返回的是true,代表事件被消費了,如果你返回的是false,那麼就算你在方法裡做了很多事,也不算消費

當OnTouchListener存在的時候,會先獲取到事件,如果不消費的話才會傳到onTouchEvent

OnTouchListener雖然優先於onTouchEvent,但都屬於同一層的消費,在這裡我們就不分開來描述了,統一描述為自己消費

(OnTouchListener > onTouchEvent)

(4)一組事件

move和up事件往往是和dowm事件相關聯的,為了簡化描述,我們這裡就把down,move,up同一稱為一組事件(下一次down事件之後的算下一組)

(5)控制元件

這裡指的所有控制元件都是在onTouch事件的點選範圍內,如果不在這個點選範圍內的控制元件,是不會參與事件傳遞的

3.傳遞路線

一個控制元件獲取到事件時,首先會走dispatchTouchEvent,才會走onInterceptTouchEvent和onTouchEvent,一般我們都不會去重寫dispatchTouchEvent方法(研究原始碼的需要重點研究這個方法),所以接下來的傳遞路線就跳過dispatchTouchEvent這個方法了

這個例子裡面只有一個ViewGroup,ViewGroup裡面有隻有一個View

onTouch 事件傳遞

4.要點

(1)攔截

①如果ViewGroup在onInterceptTouchEvent裡面攔截了down事件,那麼這一組事件都不會再進入onInterceptTouchEvent方法裡面了,也不會分配到View裡面了

(2)消費

①如果ViewGroup消費了down事件,那麼這一組事件不會進入到onInterceptTouchEvent裡面了,更不會分配到View裡面了,而是直接從dispatchTouchEvent方法走到自己消費的方法裡

(3)多個View

如果ViewGroup有多個View,那麼會從最上面的view遍歷,如果有view消費了down事件,那麼就不會繼續遍歷了,而且這一組事件也會直接進入這個view

(還會走ViewGroup的分配和攔截方法)

5.總結

onTouch事件的傳遞有很多可能的路線,這裡就不貼出筆者當初研究的DEMO程式碼了,免得看得頭暈.你只要知道幾個主要的原則和規律,再複雜的情況你也能夠知道事件會怎麼傳遞,這裡就再次總結一下

(1)一個ViewGroup有三種方法,分配,攔截,消費

  • 分配: dispatchTouchEvent
  • 攔截: onInterceptTouchEvent
  • 消費: OnTouchListener和onTouchEvent (優先走OnTouchListener的onTouch)

(View的話沒有攔截)

(2)首先事件會從父控制元件開始,逐級往下傳遞

(2)事件經過某個控制元件的時候,會先走分配,再走攔截,如果不攔截又會接著往下分配

(3)事件從上往下分配時,要麼是走到某一層被攔截了,要麼是走到最底層了才會停止向下分配

(4)一旦停止向下傳遞,就要開始考慮消費的事了

(5)從停止傳遞的那一層開始,詢問是否要消費事件,如果自己不消費,那麼逐級往上詢問

(6)一旦某層把事件消費了,那麼就不再向上詢問,事件傳遞就到此結束了

onTouch 事件傳遞

6.思維導圖

筆者當初第一次研究的時候做了一個DEMO,並把傳遞的過程用思維導圖詳細的記錄了下來,有興趣的朋友可以去下載看看,免費的哦,不過還是建議有時間的朋友能夠自己寫demo測試一下,這樣才能更好的理解.

思維導圖

download.csdn.net/download/yu…

熱門文章

相關文章