摘要:事件被上層攔截時觸發。事件返回時直接指向了父的這一部分是不合理的,實際上它僅僅是給了父的一個返回值,父根據返回值來調用自身的。是根據的返回值來確定是調用子的還是自身的,并沒有將調用交給。
原文鏈接
簡簡單單講清楚android事件分發。
什么叫事件分發機制 ?事件分發是:當發生了一個事件時,在屏幕上找到一個合適的控件來處理這個事件的過程。
因為一個界面上控件如此之多,發生一個事件后總要尋找一個合適來處理事件吧。這個過程就叫做事件分發的機制。
常見事件那么屏幕上都會發生什么事件呢?來看下經常要處理的4種事件(這些事件在android中會被封裝成 MotionEvent 對象):
事件 | 簡介 |
---|---|
ACTION_DOWN | 手指 初次接觸到屏幕 時觸發。 |
ACTION_MOVE | 手指 在屏幕上滑動 時觸發,會會多次觸發。 |
ACTION_UP | 手指 離開屏幕 時觸發。 |
ACTION_CANCEL | 事件 被上層攔截 時觸發。 |
為了在屏幕中如何尋找合適的處理事件的控件,我們先來看下屏幕中都有什么控件。
假設我們寫了如下的一個布局:
View結構:
原文鏈接上面的代碼運行到界面上由圖中這幾部分組成:
可以看到在上面的View結構中莫名多出來的兩個東西,PhoneWindow 和 DecorView ,這兩個我們并沒有在Layout文件中定義過,但是為什么會存在呢?
1. PhoneWindow事件分發流程
PhoneWindow是 Window 的唯一實現類,是所有視圖的最頂層容器,視圖的外觀和行為都歸他管,不論是背景顯示,標題欄還是事件處理都是他管理的范疇。
2. DecorView
DecorView是 PhoneWindow 的一個內部類,就是跟在 PhoneWindow 身邊專業為 PhoneWindow 服務的,除了自己要干活之外,也負責消息的傳遞,PhoneWindow 的指示通過 DecorView 傳遞給下面的 View,而下面 View 的信息也通過 DecorView 回傳給 PhoneWindow。
在如上圖View的樹形結構中,事件發生時,最先由Activity接收,然后再一層層的向下層傳遞,直到找到合適的處理控件。大致如下:
Activity -> PhoneWindow -> DecorView -> ViewGroup -> ... -> View |
---|
但是如果事件傳遞到最后的View還是沒有找到合適的View消費事件,那么事件就會向相反的方向傳遞,最終傳遞給Activity,如果最后 Activity 也沒有處理,本次事件才會被拋棄:
Activity <- PhoneWindow <- DecorView <- ViewGroup <- ... <- View |
---|
當事件發生時,ViewGroup會在dispatchTouchEvent方法中先看自己能否處理事件,如果不能再去遍歷子View查找合適的處理控件。如果到最后result還是false,表示所有的子View都不能處理,才會調用自身的onTouchEvent來處理。
根據上面提到的原理,ViewGroup事件傳遞的偽代碼如下:
public boolean dispatchTouchEvent(MotionEvent ev) { boolean result = false; // 默認狀態為沒有消費過 if (!onInterceptTouchEvent(ev)) { // 如果沒有攔截交給子View result = child.dispatchTouchEvent(ev); } if (!result) { // 如果事件沒有被消費,詢問自身onTouchEvent result = onTouchEvent(ev); } return result; }
為了方便理解,這里貼出一張網上的別人的一張圖:
紅色箭頭方向表示事件分發方向。
綠色箭頭方向表示事件回傳方向。
上面的流程中存在部分不合理內容,請大家選擇性接受。
事件返回時 dispatchTouchEvent 直接指向了父View的 onTouchEvent 這一部分是不合理的,實際上它僅僅是給了父View的 dispatchTouchEvent 一個 false 返回值,父View根據返回值來調用自身的 onTouchEvent。
ViewGroup 是根據 onInterceptTouchEvent 的返回值來確定是調用子View的 dispatchTouchEvent 還是自身的 onTouchEvent, 并沒有將調用交給 onInterceptTouchEvent。
如果在遍歷過程中,發現了有可以處理事件的控件,就停止事件的傳遞,事件被消耗。
本文參考資料:
http://www.gcssloop.com/customview/dispatch-touchevent-theory
https://juejin.im/entry/58df5b33570c35005798493c
https://juejin.im/entry/580042082e958a0055b6cbbc
https://blog.csdn.net/carson_ho/article/details/54136311
https://www.jianshu.com/p/31e20def82c2
https://segmentfault.com/a/1190000004981942
https://zhuanlan.zhihu.com/p/27608989
http://gityuan.com/2015/09/19/android-touch/
http://wuxiaolong.me/2015/12/19/MotionEvent/
推薦閱讀:
推薦閱讀:
Android開發藝術探索
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/73365.html
摘要:前端基礎進階正是圍繞這條線索慢慢展開,而事件循環機制,則是這條線索的最關鍵的知識點。特別是中正式加入了對象之后,對于新標準中事件循環機制的理解就變得更加重要。之后全局上下文進入函數調用棧。 showImg(https://segmentfault.com/img/remote/1460000008811705); JavaScript的學習零散而龐雜,因此很多時候我們學到了一些東西,但...
閱讀 1756·2021-11-24 09:39
閱讀 1686·2021-11-22 15:22
閱讀 1002·2021-09-27 13:36
閱讀 3230·2021-09-24 10:34
閱讀 3329·2021-07-26 23:38
閱讀 2633·2019-08-29 16:44
閱讀 974·2019-08-29 16:39
閱讀 1104·2019-08-29 16:20