在Android中主要存在兩種事件,一種是按鍵事件,對應物理按鍵或者虛擬按鍵,一種是觸摸屏事件。本文主要了解觸摸消息的傳遞過程,以及可以對消息做什麼處理。是驗證性質分析!
對於所有的消息處理,底層的東東,應用工程師不太關心,不過要大致知道是什麼情況,其總的過程如下所示。
在具體的調用過程中,涉及到了幾個具體的函數,是需要弄清楚的。
1.dispatchTouchEvent(MotionEvent ev) 這個只有在Acitity和ViewGroup中才有,View是沒有這樣的函數。這個函數會進行消息派發。
2.onIntercepTouchEvent(MotionEvent ev)這個只有在ViewGroup纔有用,它提供一種能力,能夠截斷消息的派發,後面會說到截斷的效果。
如果返回True則進行截斷。如果它有子控件調用了requestDisallowInterceptTouchEvent(),這個方法是不會調用的。
3.onTouchEvent(),這個函數Activity,ViewGroup ,View 都可以進行重載。經常有一種說法,就是這個函數如果返回True,則代表這個函數可以消費了這個事 件,所謂的消費了這個事件,就是指定當前的View是這個消息處理過程中的目標。
爲了查看具體的情況,寫了一個小的Demo.其視圖如下所示:
通過做試驗,得出了下圖:
以上消息拿Activity對應的窗口進行舉例(不包含對話框和popupWindow等)
觸摸的消息從動作DOWN開始,UP或者CANCEL結束,中間一般可以有MOVE等操作。
消息分爲兩部分。DOWN消息和其它消息。
DOWN消息有些特殊,在DOWN消息派發的過程中,要定位這次消息流程目標是哪個控件,也就是找到誰的OnTouchEvent返回是True。
如果所有的onTouchEvent都返回false,最終的消息目標是activity中的onTouchEvent();上圖中黑色實線所應對就是這種情況下DOWN消息的派發過程。
爲什麼反覆的強調一次完成消息派發過程中的目標。因爲非DOWN消息和DOWN不一樣的。
DEMO中可以試試。
DOWN 消息派發過程:
結論一:消息的派發自頂向下,由根樹圖開始(如果是Activity對應就是DecorView,如果是對話框等就是其最外層的ViewGroup,流動像一個U形
結論二:如果onInterceptTouchEvent()返回了True,並且該控件允許截斷,則消息不會往下流動,直接調用本層的OnTouchEvent();
結論三:如果在消息派發的路線上,有onTouchEvetn()返回True,其上層控件的onTouchEvent()都不會調用。假定MyViewGroup返回True
非DOWN消息派發過程:
結論一:與DOWN消息派發不同,如果當前控件就是這次消息目標,其下層的控件的消息相關都不會派發(只有目標控件的OnTouchEvent會調用)。假定MyViewGroup在DOWN消息派發過程中確定爲目標。(這次流動的轉折不是因爲截斷)
其實仔細想想,其設計還是很合理的,剛開始按下的時候,爲什麼要繞一大圈形成一個U形,是爲了找到目標。找到目標後除了DOWN以外的消息都是精準投遞,沒有產生浪費。
上面的DEMO地址:https://github.com/ArronXiao/VerifyDemo 以後的驗證也會在上面更新,持續維護!