Android Touch事件的分發過程

來源:互聯網
上載者:User

標籤:

一.不知道你是否在涉及到Android觸屏事件的時候有過如下的疑問:

1.View的onTouchEvent()方法返回true和false有什麼區別? SDK給出的解釋很簡單:"返回true代表該事件已經被處理過了,返回false則相反",這句話完全沒有解釋清楚問題。

2.View的onTouchEvent()方法在處理ACTION_DOWN的時候返回true,在處理ACTION_MOVE的時候返回false,代表著是處理了還是沒處理?返回super.onTouchEvent()又是什麼含義?

3.重寫onTouchEvent()方法和通過setOnTouchListener()設定一個觸屏監聽有什麼區別,看起來好像很類似。

4.View的dispatchTouchEvent(),onTouchEvent(),setOnClickListener(),ViewGroup的onInterceptTouchEvent()把我繞暈了,這些方法怎麼使用怎麼重寫?

5.假設一個ViewGroup有兩個子view,這兩個view有一部分是重疊的,點擊該重疊部分,事件由哪個View來處理?

6.最重要的一點疑問是:觸屏事件從頂層ViewGroup一直向下是怎麼傳遞的?

如果你有類似的疑問,相信我的這篇部落格能給你答案。

二.首先需要明確的幾點是:

1.View一般是為了顯示某些內容而存在的,它也通常用來處理使用者的觸屏等互動事件,而ViewGroup則是做為View的容器而存在的,雖然在代碼上它是View的子類,但它通常只是做為容器用來組織它的子視圖布局方式。

2.我們知道android裡邊View層次是一種樹型結構,需要明確的是一個ViewGroup它的直接子視圖才算是樹結構中的兒子,再往下一層就不算了,類似於進程間的父子關係。舉例,FrameLayout有兩個子視圖,分別是LinearLayout和TextView,而 LinearLayout又有三個子視圖ImageView,那麼調用FrameLayout的getChildCount()方法只會返回2,而不是 5。因此以下內容中"子視圖"這個術語代表著一個ViewGroup的直接子視圖,它即可能是一個View類,也可能是一個ViewGroup類。

3.Activity視圖的最頂層View是DecorView,它是在PhoneWindow類中通過generateDecor()方法產生的,它繼承自FrameLayout,是View層次的根視圖。

4.對於觸屏來說有三個主要的事件:down,move,up

那麼一個觸屏事件到底是怎麼在View層次中上向下傳遞的?(這裡只考慮事件已經到達DecorView時的情形,事實上是ViewRootImpl 類接收到底層InputDispatch傳遞過來的事件,這裡就不寫了),ViewRootImpl在deliverPointerEvent()方法中通過調用mView.dispatchPointerEvent(event);將觸屏事件傳遞給了DecorView,DecorView通過 dispatchTouchEvent()繼續向下傳遞給子視圖,如果子視圖也是一個ViewGroup,它又會調用自己的 dispatchTouchEvent()方法向下傳遞,如果子視圖是一個View,那麼子視圖的onTouchEvent()方法就會被調用,如果子視圖處理了該事件,那麼事件傳遞就中止。整個過程像是一個遞迴過程,理解了一個ViewGroup怎麼通過dispatchTouchEvent()傳遞給它的子視圖這一層也就理解了整個過程。

這裡就不分析ViewGroup的dispatchTouchEvent()方法的代碼了,直接給出我總結出來的結論,有興趣的讀者可以分析看看。

三.總結

以下情景假設一個ViewGroup有三個子視圖,按index順序為v1,v2,v3。v1也是一個ViewGroup,v2和v3都是普通的view,而且它們有一點重疊的部分。

1.ViewGroup的dispatchTouchEvent()向下分發事件給它的子視圖,那麼會先分發給v3調用它的onTouchEvent 方法,如果v3不處理該事件,會繼續分發給v2,如果v2不處理事件,會繼續分發給v1,由於v1是一個ViewGroup,則會調用它的 dispatchTouchEvent()分發給它的子視圖。

2.v3不處理該事件的含義是:在down事件到達時,onTouchEvent()方法返回false,如果在接收到down事件時返回true, 則表示處理了該事件,那麼不管你在接收到move和up事件的時候返回的是什麼都沒有關係。因此思想是:只要你願意處理down事件,那麼你必須處理接下來的其他事件。

3.v3能接收觸屏事件的前提是它的顯示矩形框必須在觸屏的範圍之內,這裡顯而易見的道理,否則事件會傳遞給v2。

4.如果v1,v2,v3都決定不處理觸屏事件,那麼事件最終由ViewGroup自己來處理,它的onTouchEvent()方法會被調用。

5.如果事件傳遞到了v1,v1是否處理取決於它的子視圖,如果它的子視圖有一個處理了該事件,那麼就代表v1處理了事件,如果它的所有子視圖都沒有處理事件而且v1本身的onTouchEvent()的方法在處理down事件的時候返回false,那麼才代表v1沒有處理事件。

6.如果通過setOnTouchListener()設定了一個有效監聽到view中,那麼事件到達時會直接調用這個監聽方法而不會調用onTouchEvent(),並返回true,表示已經處理了該事件。

到這裡,onTouchEvent()傳回值的含義應該很明確了,那麼super.onTouchEvent()傳回值是什麼呢?看代碼也比較簡單,如果一個view不是clickable的或者不是longClickable的,那麼super.onTouchEvent()直接返回false,否則就進行onClick和onLongClick處理並返回true。可調用 setClickable(true),setLongClickable(true)來改變view的狀態,調用 setOnClickListener()和setOnLongClickListener()也是一樣的效果。

由上面結論,如果兩視圖是父弟關係,它們又互有重疊部分,點擊該重疊部分,先處理該事件的是下標比較大的那個視圖,如果這個視圖不想處理事件,才讓另外一個處理。

四.onInterceptTouchEvent()

ViewGroup可以調用它的onInterceptTouchEvent()方法去攔截子視圖的事件,這個方法預設返回的是false表示不攔截,如果在onInterceptTouchEvent()接收到down事件時返回了true,那麼接下來的down,move和up事件都會被 ViewGroup自己的onTouchEvent()方法所接收,所有的子視圖都接收不到事件,而ViewGroup自己的 onInterceptTouchEvent()方法也只有down事件會被傳遞過去,因為都由父View來處理,所以該方法再接收到move和up事件就沒有意義了,所以只會有down事件會被傳遞。注釋中的說法:There are no touch targets and this action is not an initial down,so this view group continues to intercept touches.

如果一個子視圖決定處理全部三個事件,那麼每次事件到來時都會先調用父view的onInterceptTouchEvent()方法,如果在某個事件上返回了true,那麼就會攔截到該事件以及隨後的事件到ViewGroup自己的onTouchEvent()方法處理,子視圖會接收到 ACTION_CANCEL事件。

舉例:如果子視圖處理了down事件,但是ViewGroup在move到來時攔截住了move事件,那麼子視圖就收不到接下來的move和up事件,會收到ACTION_CANCEL事件,而ViewGroup則會接收move和up事件,onInterceptTouchEvent()方法也只會接收到down和move事件。

攔截方法有時非常有用,例如ScrollView它會先把down事件交給子視圖處理,如果是點擊事件,就交給子視圖,如果判斷出來正在拖動子視圖,那麼會攔截住move事件,交由自己處理,調用overScrollBy()產生滾動。

當然如果自己重寫了ViewGroup的dispatchTouchEvent()方法就自己掌控了事件的分發過程,和上面的流程就不一定一樣了。

總結完了,相信開頭的所有問題都有了答案,有點繞人,理清了就明白了。

轉載自:http://www.bdqn.cn/news/201312/12158.shtml

Android Touch事件的分發過程

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.