1. 程式人生 > >可能是最詳細的Android點選事件處理詳解

可能是最詳細的Android點選事件處理詳解

面試的時候,很多時候都會問到Touch事件的傳遞,而且問法角度都有所不同,但是還是會遵循基本的事件傳遞規則的,可能他問的你沒處理過,但是根據基本規則慢慢思考來回答,都不會錯。

image

一,簡介

首先我們知道touch事件 主要是是在三個方法中傳遞和處理的。分別是:
- dispatchTouchEvent 事件分發
- onInterceptTouchEvent 事件攔截
- onTouchEvent 事件處理

其中事件攔截的方法只在VeiwGroup中有,Activity和View中都沒有,而事件的傳遞遵循從上到下分發->攔截。而處理則是從內到外的反饋過程,然後在從外到內的分發完成,最後在處理層呼叫onTouchEvent的ACTION_UP至此,事件的分發和處理走完。這裡大家先有一個印象,後面還會詳細講解。

二,頁面佈局

如上圖頁面所示:主要包含TouchNormalActivity,注意這個activity要繼承系統自帶AppCompatActivity或者其他,不要繼承自己封裝的Activity,有可能你封裝的時候做了處理,自己不知道,會出現事件傳遞不準確的情況。
頁面包含三層:TouchNormalActivity->NormalViewGroup->NormalView

三,事件處理onTouchEvent.ACTION_DOWN

下面事件處理只有DOWN事件的日誌

1),三層都不處理touch事件

三層都不處理,按照系統預設處理來進行
日誌如下:
TouchNormalActivity[dispatchTouchEvent, 29]: ACTION_DOWN
NormalViewGroup[dispatchTouchEvent, 35]: ACTION_DOWN
NormalViewGroup[onInterceptTouchEvent, 61]: ACTION_DOWN
NormalView[dispatchTouchEvent, 63]: ACTION_DOWN
NormalView[onTouchEvent, 89]: ACTION_DOWN
NormalViewGroup[onTouchEvent, 88]: ACTION_DOWN
TouchNormalActivity[onTouchEvent, 56]: ACTION_DOWN
TouchNormalActivity[dispatchTouchEvent, 37]: ACTION_UP
TouchNormalActivity[onTouchEvent, 63]: ACTION_UP

我們可以看到遵循我們在簡介中說的情況。

2),View層消費touch事件

這裡主要指在最內層處理了點選事件可以是該View實現了OnClickListener介面,也可以是在onTouchEvent裡面返回了true。
日誌如下:
TouchNormalActivity[dispatchTouchEvent, 29]: ACTION_DOWN
NormalViewGroup[dispatchTouchEvent, 35]: ACTION_DOWN
NormalViewGroup[onInterceptTouchEvent, 61]: ACTION_DOWN
NormalView[dispatchTouchEvent, 63]: ACTION_DOWN
NormalView[onTouchEvent, 89]: ACTION_DOWN
TouchNormalActivity[dispatchTouchEvent, 37]: ACTION_UP
NormalViewGroup[dispatchTouchEvent, 42]: ACTION_UP
NormalView[dispatchTouchEvent, 70]: ACTION_UP
NormalView[onTouchEvent, 96]: ACTION_UP

從日誌我們可以看到,當內層View消費掉點選事件的時候,就不會在呼叫super.onTouchEvent(event);去詢問父View是否要處理該事件。跟1)相比少了一個,從內到外反饋詢問是否處理點選事件的過程。

因為內層View已經處理了點選事件,這個時候我們可以認為本地點選事件已經分發完畢,從日誌我們可以清楚的看到有一個從外到內通知事件分發完畢的過程,一直到處理事件層的dispatchTouchEvent.ACTION_UP。表示事件分發到這一層完畢,然後才會去執行onTouchEvent的UP事件,至此表示該事件處理完畢。

3),ViewGroup層消費touch事件

首先我們必須明白的一件事是,事件的分發是從外到內的過程,但是事件的處理是從內到外的過程,手指點選到螢幕,雖然是在最外層,但是事件處理的時候。要優先詢問最內層的是否處理,然後在往外層一層一層的詢問,這樣才能保證事件處理不會亂。

這裡再次重複說這個,是因為想讓大家看清楚 view 層 和 viewgroup層處理日誌的不同

日誌如下:
TouchNormalActivity[dispatchTouchEvent, 29]: ACTION_DOWN
NormalViewGroup[dispatchTouchEvent, 35]: ACTION_DOWN
NormalViewGroup[onInterceptTouchEvent, 61]: ACTION_DOWN
NormalView[dispatchTouchEvent, 63]: ACTION_DOWN
NormalView[onTouchEvent, 89]: ACTION_DOWN
NormalViewGroup[onTouchEvent, 88]: ACTION_DOWN
TouchNormalActivity[dispatchTouchEvent, 37]: ACTION_UP
NormalViewGroup[dispatchTouchEvent, 42]: ACTION_UP
NormalViewGroup[onTouchEvent, 95]: ACTION_UP

正如上面說的,雖然我們是在ViewGroup消費掉了點選事件,但是發現View層也是可以接收到ACTION_DOWN 然後再往外反饋的。

4),Activity層消費touch事件

經過了Viewgroup層的講述,相信activity層大家已經能猜到了
日誌如下:
TouchNormalActivity[dispatchTouchEvent, 29]: ACTION_DOWN
NormalViewGroup[dispatchTouchEvent, 35]: ACTION_DOWN
NormalViewGroup[onInterceptTouchEvent, 61]: ACTION_DOWN
NormalView[dispatchTouchEvent, 63]: ACTION_DOWN
NormalView[onTouchEvent, 89]: ACTION_DOWN
NormalViewGroup[onTouchEvent, 88]: ACTION_DOWN
TouchNormalActivity[onTouchEvent, 56]: ACTION_DOWN
TouchNormalActivity[dispatchTouchEvent, 37]: ACTION_UP
TouchNormalActivity[onTouchEvent, 63]: ACTION_UP

我們會發現 這個日誌和三層都不處理的日誌是一樣的。因為已經到了最上層,你不處理誰處理。所以日誌一樣。

四,事件處理onTouchEvent.ACTION_MOVE

我們發現MOVE事件的前期過程和DOWN事件一樣,只不過在down到事件消費層的時候。開始從外網內再次分發了一個MOVE事件。然後在UP的時候 和 DOWN是一樣的。

1),三層都不處理touch事件,此時的MOVE

三層都不處理,按照系統預設處理來進行
日誌如下:
TouchNormalActivity[dispatchTouchEvent, 29]: ACTION_DOWN
NormalViewGroup[dispatchTouchEvent, 35]: ACTION_DOWN
NormalViewGroup[onInterceptTouchEvent, 61]: ACTION_DOWN
NormalView[dispatchTouchEvent, 63]: ACTION_DOWN
NormalView[onTouchEvent, 89]: ACTION_DOWN
NormalViewGroup[onTouchEvent, 88]: ACTION_DOWN
TouchNormalActivity[onTouchEvent, 56]: ACTION_DOWN
TouchNormalActivity[dispatchTouchEvent, 33]: ACTION_MOVE
TouchNormalActivity[onTouchEvent, 60]: ACTION_MOVE
TouchNormalActivity[dispatchTouchEvent, 37]: ACTION_UP
TouchNormalActivity[onTouchEvent, 63]: ACTION_UP

我們能夠看到。MOVE事件,是在ACTION_DOWN事件傳遞和處理完畢以後才進行MOVE處理的。這個時候已經能夠確定那一層來消費touchEvent事件了。所以就再次來分發事件,因為已經能確定在Activity層處理事件了。就不會往內層分發,直接分發完,在該層的onTouchEvent中進行處理了。

2),View處理touch事件,此時的MOVE

TouchNormalActivity[dispatchTouchEvent, 29]: ACTION_DOWN
NormalViewGroup[dispatchTouchEvent, 35]: ACTION_DOWN
NormalViewGroup[onInterceptTouchEvent, 61]: ACTION_DOWN
NormalView[dispatchTouchEvent, 63]: ACTION_DOWN
NormalView[onTouchEvent, 89]: ACTION_DOWN
TouchNormalActivity[dispatchTouchEvent, 33]: ACTION_MOVE
NormalViewGroup[dispatchTouchEvent, 39]: ACTION_MOVE
NormalViewGroup[onInterceptTouchEvent, 65]: ACTION_MOVE
NormalView[dispatchTouchEvent, 67]: ACTION_MOVE
NormalView[onTouchEvent, 93]: ACTION_MOVE
TouchNormalActivity[dispatchTouchEvent, 37]: ACTION_UP
NormalViewGroup[dispatchTouchEvent, 42]: ACTION_UP
NormalViewGroup[onInterceptTouchEvent, 69]: ACTION_UP
NormalView[dispatchTouchEvent, 70]: ACTION_UP
NormalView[onTouchEvent, 96]: ACTION_UP

我們發現這個過程其實和Down是一樣的,只不過多了一個Move的一個分發和處理

五,事件攔截onInterceptTouchEvent

1),ViewGroup中做事件攔截,各層都不處理事件

這個攔截沒有細分,直接在onInterceptTouchEvent中返回true了。
日誌如下:
TouchNormalActivity[dispatchTouchEvent, 29]: ACTION_DOWN
NormalViewGroup[dispatchTouchEvent, 35]: ACTION_DOWN
NormalViewGroup[onInterceptTouchEvent, 61]: ACTION_DOWN
NormalViewGroup[onTouchEvent, 88]: ACTION_DOWN
TouchNormalActivity[onTouchEvent, 56]: ACTION_DOWN
TouchNormalActivity[dispatchTouchEvent, 37]: ACTION_UP
TouchNormalActivity[onTouchEvent, 63]: ACTION_UP

因為ViewGroup做了攔截,在內層View中根本就接受不到事件。

這個時候想一下MOVE事件的情況,因為ViewGroup雖然攔截了,但是並沒有處理事件,所以還需要網上反饋,最終在最上層做處理。所以此時的MOVE只會在最上層(activity)的dispatchTouchEvent和onTouchEvent中執行。

2),ViewGroup中做事件攔截,並在ViewGroup中處理事件

日誌如下:
TouchNormalActivity[dispatchTouchEvent, 29]: ACTION_DOWN
NormalViewGroup[dispatchTouchEvent, 35]: ACTION_DOWN
NormalViewGroup[onInterceptTouchEvent, 61]: ACTION_DOWN
NormalViewGroup[onTouchEvent, 88]: ACTION_DOWN
TouchNormalActivity[dispatchTouchEvent, 37]: ACTION_UP
NormalViewGroup[dispatchTouchEvent, 42]: ACTION_UP
NormalViewGroup[onTouchEvent, 95]: ACTION_UP

我們能看到。攔截只是不往內層傳遞,其他的都還是一樣的。

但是區別在於MOVE事件。首先攔截以後 就會直接走當前層的onTouchEvent方法。如果我們不處理,就會向上反饋,MOVE的時候就會在上層MOVE

如果在ViewGroup中消費點選事件,那麼在MOVE的時候是在ViewGroup中MOVE,分發完DOWN事件以後再次有外網內進行分發MOVE事件。

3),ViewGroup中做MOVE事件攔截

首先我們必須知道一點,MOVE事件是,你那一層要消費那一次才能得到MOVE的分發。如果我們都沒有去處理DOWN事件,那麼我們在MOVE的時候,ViewGroup和View是得不到MOVE事件的。

因此,我們在ViewGroup做MOVE攔截,就必須保障ViewGroup的內層View要消費點選事件。

因為我們只攔截了MOVE事件,所以DOWN事件的日誌和DOWN三層都不處理的日誌是一樣的。

MOVE日誌如下:
TouchNormalActivity[dispatchTouchEvent, 29]: ACTION_DOWN
NormalViewGroup[dispatchTouchEvent, 35]: ACTION_DOWN
NormalViewGroup[onInterceptTouchEvent, 61]: ACTION_DOWN
NormalView[dispatchTouchEvent, 63]: ACTION_DOWN
NormalView[onTouchEvent, 89]: ACTION_DOWN

TouchNormalActivity[dispatchTouchEvent, 33]: ACTION_MOVE
NormalViewGroup[dispatchTouchEvent, 39]: ACTION_MOVE
NormalViewGroup[onInterceptTouchEvent, 65]: ACTION_MOVE
NormalView[dispatchTouchEvent, 74]: ACTION_CANCEL
NormalView[onTouchEvent, 100]: ACTION_CANCEL

TouchNormalActivity[dispatchTouchEvent, 33]: ACTION_MOVE
NormalViewGroup[dispatchTouchEvent, 39]: ACTION_MOVE
NormalViewGroup[onTouchEvent, 92]: ACTION_MOVE
TouchNormalActivity[onTouchEvent, 60]: ACTION_MOVE

TouchNormalActivity[dispatchTouchEvent, 37]: ACTION_UP
NormalViewGroup[dispatchTouchEvent, 42]: ACTION_UP
NormalViewGroup[onTouchEvent, 95]: ACTION_UP
TouchNormalActivity[onTouchEvent, 63]: ACTION_UP

從日誌中我們可以看到。主要分為四段,第一段是Down事件的處理,因為攔截的是move所以,down還是能進入到最底層View並且消費掉事件,然後開始進行MOVE,因為最底層View消費掉事件,道理上MOVE應該是可以分發到View層的,但是因為在上層的Viewgroup做了攔截,我們能夠看到在View層的dispatchTouchEvent和onTouchEvent給到的狀態是ACTION_CANCEL就是取消當前View事件的處理,然後再次重新分發MOVE事件。同事因為做了攔截,所以onInterceptTouchEvent不執行。

4),ViewGroup中做UP事件攔截

本來覺得UP事件攔截有什麼好做的,沒什麼用。後來試了下,發現也有點意思。

我們在View層 添加了onClick方法。並在Viewgroup做UP攔截。

不攔截日誌如下:
NormalViewGroup[onInterceptTouchEvent, 61]: ACTION_DOWN
NormalView[dispatchTouchEvent, 63]: ACTION_DOWN
NormalView[onTouchEvent, 89]: ACTION_DOWN
TouchNormalActivity[dispatchTouchEvent, 37]: ACTION_UP
NormalViewGroup[dispatchTouchEvent, 42]: ACTION_UP
NormalViewGroup[onInterceptTouchEvent, 69]: ACTION_UP
NormalView[dispatchTouchEvent, 70]: ACTION_UP
NormalView[onTouchEvent, 96]: ACTION_UP
NormalView$1[onClick, 47]: onClick: ======

這是一個正常在View消費事件的日誌,並且答應了onClick日誌。

攔截日誌:
TouchNormalActivity[dispatchTouchEvent, 29]: ACTION_DOWN
NormalViewGroup[dispatchTouchEvent, 35]: ACTION_DOWN
NormalViewGroup[onInterceptTouchEvent, 61]: ACTION_DOWN
NormalView[dispatchTouchEvent, 63]: ACTION_DOWN
NormalView[onTouchEvent, 89]: ACTION_DOWN
TouchNormalActivity[dispatchTouchEvent, 37]: ACTION_UP
NormalViewGroup[dispatchTouchEvent, 42]: ACTION_UP
NormalViewGroup[onInterceptTouchEvent, 69]: ACTION_UP
NormalView[dispatchTouchEvent, 74]: ACTION_CANCEL
NormalView[onTouchEvent, 100]: ACTION_CANCEL

從日誌我們可以看到,在執行到ViewGroup的onInterceptTouchEvent的UP事件以後,後面的變成ACTION_CANCEL事件了。

因為我們做了分發的攔截,系統可以認為該事件不需要在往下分發了。或者認為分發失敗。然後去呼叫CANCEL來通知下層。該事件重置或者取消了。

六,事件分發dispatchTouchEvent

1),View層做事件分發攔截

1,

在View層添加了onClick事件,但是在View層的dispatchTouchEvent.ACTION_DOWN返回true

日誌如下:
TouchNormalActivity[dispatchTouchEvent, 29]: ACTION_DOWN
NormalViewGroup[dispatchTouchEvent, 35]: ACTION_DOWN
NormalViewGroup[onInterceptTouchEvent, 61]: ACTION_DOWN
NormalView[dispatchTouchEvent, 63]: ACTION_DOWN
TouchNormalActivity[dispatchTouchEvent, 37]: ACTION_UP
NormalViewGroup[dispatchTouchEvent, 42]: ACTION_UP
NormalViewGroup[onInterceptTouchEvent, 69]: ACTION_UP
NormalView[dispatchTouchEvent, 70]: ACTION_UP
NormalView[onTouchEvent, 96]: ACTION_UP

onClick沒有執行。

在View層的dispatchTouchEvent.ACTION_DOWN返回true 以後,就沒有走View的onTouchEvent了。會認為事件在分發的時候已經完成,然後從外到內走分發完成的過程。

2,

在View層添加了onClick事件,但是在View層的dispatchTouchEvent.ACTION_UP返回true

日誌如下:
TouchNormalActivity[dispatchTouchEvent, 29]: ACTION_DOWN
NormalViewGroup[dispatchTouchEvent, 35]: ACTION_DOWN
NormalViewGroup[onInterceptTouchEvent, 61]: ACTION_DOWN
NormalView[dispatchTouchEvent, 63]: ACTION_DOWN
NormalView[onTouchEvent, 89]: ACTION_DOWN
TouchNormalActivity[dispatchTouchEvent, 37]: ACTION_UP
NormalViewGroup[dispatchTouchEvent, 42]: ACTION_UP
NormalViewGroup[onInterceptTouchEvent, 69]: ACTION_UP
NormalView[dispatchTouchEvent, 70]: ACTION_UP

跟我想象中的還是有點出入的,onClick不執行是肯定的。我以為會呼叫ACTION_CANCEL結果並沒有。

只是比正常流程少了一步onTouchEvent.ACTION_UP而導致 onClick不執行。

2),ViewGroup層做事件分發攔截

1,

在View層添加了onClick事件,但是在ViewGroup層的dispatchTouchEvent.ACTION_DOWN返回true

日誌如下:
TouchNormalActivity[dispatchTouchEvent, 29]: ACTION_DOWN
NormalViewGroup[dispatchTouchEvent, 35]: ACTION_DOWN
TouchNormalActivity[dispatchTouchEvent, 37]: ACTION_UP
NormalViewGroup[dispatchTouchEvent, 42]: ACTION_UP
NormalViewGroup[onTouchEvent, 95]: ACTION_UP
TouchNormalActivity[onTouchEvent, 64]: ACTION_UP

onClick沒有執行。

在ViewGroup層的dispatchTouchEvent.ACTION_DOWN返回true 以後,就會認為在ViewGroup分發完成,然後在由外到內去呼叫分發的up事件。但是我們會發現一個很奇怪的現象,就是ViewGroup層的onTouchEvent.down事件因為在分發的down中被返回,所以並沒有執行,但是他的up事件卻執行了。並且因為Viewgroup並沒有處理事件,up事件還向上反饋了。

2,

在View層添加了onClick事件,但是在ViewGroup層的dispatchTouchEvent.ACTION_UP返回true

日誌如下:
TouchNormalActivity[dispatchTouchEvent, 29]: ACTION_DOWN
NormalViewGroup[dispatchTouchEvent, 35]: ACTION_DOWN
NormalViewGroup[onInterceptTouchEvent, 61]: ACTION_DOWN
NormalView[dispatchTouchEvent, 63]: ACTION_DOWN
NormalView[onTouchEvent, 89]: ACTION_DOWN
TouchNormalActivity[dispatchTouchEvent, 37]: ACTION_UP
NormalViewGroup[dispatchTouchEvent, 42]: ACTION_UP

在ViewGroup的dispatchTouchEvent.ACTION_UP以後的都不執行了。所以造成onClick也不會執行。

3),Activity層做事件分發攔截

1,

在View層添加了onClick事件,但是在Activity層的dispatchTouchEvent.ACTION_DOWN返回true

日誌如下:
TouchNormalActivity[dispatchTouchEvent, 29]: ACTION_DOWN

TouchNormalActivity[dispatchTouchEvent, 37]: ACTION_UP
TouchNormalActivity[onTouchEvent, 64]: ACTION_UP

onClick沒有執行。

對比ViewGroup一目瞭然

2,

在View層添加了onClick事件,但是在Activity層的dispatchTouchEvent.ACTION_UP返回true

日誌如下:
TouchNormalActivity[dispatchTouchEvent, 29]: ACTION_DOWN
NormalViewGroup[dispatchTouchEvent, 46]: ACTION_CANCEL
NormalViewGroup[onInterceptTouchEvent, 73]: ACTION_CANCEL
NormalView[dispatchTouchEvent, 74]: ACTION_CANCEL
NormalView[onTouchEvent, 100]: ACTION_CANCEL
NormalViewGroup[dispatchTouchEvent, 35]: ACTION_DOWN
NormalViewGroup[onInterceptTouchEvent, 61]: ACTION_DOWN
NormalView[dispatchTouchEvent, 63]: ACTION_DOWN
NormalView[onTouchEvent, 89]: ACTION_DOWN
TouchNormalActivity[dispatchTouchEvent, 37]: ACTION_UP

onClick不執行

同時這個日誌很奇特,我們在Activity的分發UP中返回true,我以為回像Viewgroup那樣down事件向下傳遞,然後後面的不執行分發的up,沒想到打印出的日誌竟然是這樣的。

從日誌我們可以看出來先從上到下執行了一次Cancel,然後在執行了了一遍down,然後在Activity層的up事件終止。(這裡我也不是很明白,帶後續研究)

總結:
在分發的down和up分別做處理,我們能看出來的是,如果在down中處理,其實就等於在上層做了攔截,但是如果實在up中做處理,事件還是能進入到最底層View中的。

還有就是在分發的時候MOVE事件的處理情況,有興趣的同學可以看一下,記住MOVE的處理層級是在down層級的。記住這一點,就能很快知道MOVE可以深入到那一層。

七,setOnTouchListener

1,

給View設定 setOnTouchListener 和 setOnClickListener

日誌如下:

TouchNormalActivity[dispatchTouchEvent, 29]: ACTION_DOWN
NormalViewGroup[dispatchTouchEvent, 35]: ACTION_DOWN
NormalViewGroup[onInterceptTouchEvent, 61]: ACTION_DOWN
NormalView[dispatchTouchEvent, 65]: ACTION_DOWN
NormalView$2[onTouch, 55]: onTouch
NormalView[onTouchEvent, 91]: ACTION_DOWN
TouchNormalActivity[dispatchTouchEvent, 37]: ACTION_UP
NormalViewGroup[dispatchTouchEvent, 42]: ACTION_UP
NormalViewGroup[onInterceptTouchEvent, 69]: ACTION_UP
NormalView[dispatchTouchEvent, 72]: ACTION_UP
NormalView[onTouch, 55]: onTouch
NormalView[onTouchEvent, 98]: ACTION_UP
NormalView[onClick, 49]: onClick

我們能看到 onTouchListener優先於onClick執行,先於onTouchEvent執行。

2,

setOnTouchListener 返回true的時候

日誌如下:
TouchNormalActivity[dispatchTouchEvent, 29]: ACTION_DOWN
NormalViewGroup[dispatchTouchEvent, 35]: ACTION_DOWN
NormalViewGroup[onInterceptTouchEvent, 61]: ACTION_DOWN
NormalView[dispatchTouchEvent, 65]: ACTION_DOWN
NormalView[onTouch, 55]: onTouch
TouchNormalActivity[dispatchTouchEvent, 37]: ACTION_UP
NormalViewGroup[dispatchTouchEvent, 42]: ACTION_UP
NormalViewGroup[onInterceptTouchEvent, 69]: ACTION_UP
NormalView[dispatchTouchEvent, 72]: ACTION_UP
NormalView[onTouch, 55]: onTouch

從日誌我們看到,因為onTouch是優先於onClick執行的,當onTouch返回true的時候,事件就沒有傳遞到View層的onTouchEvent.ACTION_DOWN中。所以onClick並沒有執行。

八,setOnClickListener

在View新增onClick事件,日誌如下:

TouchNormalActivity[dispatchTouchEvent, 29]: ACTION_DOWN
NormalViewGroup[dispatchTouchEvent, 35]: ACTION_DOWN
NormalViewGroup[onInterceptTouchEvent, 61]: ACTION_DOWN
NormalView[dispatchTouchEvent, 63]: ACTION_DOWN
NormalView[onTouchEvent, 89]: ACTION_DOWN
TouchNormalActivity[dispatchTouchEvent, 37]: ACTION_UP
NormalViewGroup[dispatchTouchEvent, 42]: ACTION_UP
NormalViewGroup[onInterceptTouchEvent, 69]: ACTION_UP
NormalView[dispatchTouchEvent, 70]: ACTION_UP
NormalView[onTouchEvent, 96]: ACTION_UP
NormalView$1[onClick, 47]: onClick

我們可以看到 onClick執行是在View層的onTouchEvent.ACTION_UP以後執行的,此時如果我們在View層的 dispatchTouchEvent.ACTION_UP或者onTouchEvent.ACTION_UP直接返回true,都會導致onClick不會執行。

九,總結

以上就是Touch事件的傳遞和攔截過程。看起來有一些枯燥,其實自己跟一遍流程,還有有些感悟和收穫的。

首先我們要記住,事件的傳遞流程是 分發->攔截->處理。

具體過程為,我們點選一個螢幕的時候,肯定是外部最先接觸到點選事件,但是為了保證內部能處理到事件,所以我們需要一個從內到外反饋的過程,因為事件是先從外到內分發和攔截down事件,然後到達最內層View的onTouchEvent處理事件,然後在從內到外來進行反饋,那一層要處理該事件。

當該層要處理down事件以後。在從外到內來分發和攔截up事件,到處理層的onTouchEvent.ACTION_UP終止。

同時呢,MOVE事件是在down的處理層進行的。先進行down處理,進入到處理層級,然後從外到內傳遞MOVE。如果內層都不做處理,那麼就只有在外層的分發和處理裡面才有MOVE回撥。

專案原始碼:
https://github.com/wangxp423/ViewExercise

在首頁的Touch事件研究中。