亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

Android-View進(jìn)階-事件分發(fā)機(jī)制原理

pkwenda / 3480人閱讀

摘要:事件被上層攔截時(shí)觸發(fā)。事件返回時(shí)直接指向了父的這一部分是不合理的,實(shí)際上它僅僅是給了父的一個(gè)返回值,父根據(jù)返回值來調(diào)用自身的。是根據(jù)的返回值來確定是調(diào)用子的還是自身的,并沒有將調(diào)用交給。

原文鏈接

簡簡單單講清楚android事件分發(fā)。

什么叫事件分發(fā)機(jī)制 ?

事件分發(fā)是:當(dāng)發(fā)生了一個(gè)事件時(shí),在屏幕上找到一個(gè)合適的控件來處理這個(gè)事件的過程。

因?yàn)橐粋€(gè)界面上控件如此之多,發(fā)生一個(gè)事件后總要尋找一個(gè)合適來處理事件吧。這個(gè)過程就叫做事件分發(fā)的機(jī)制。

常見事件

那么屏幕上都會發(fā)生什么事件呢?來看下經(jīng)常要處理的4種事件(這些事件在android中會被封裝成 MotionEvent 對象):

事件 簡介
ACTION_DOWN 手指 初次接觸到屏幕 時(shí)觸發(fā)。
ACTION_MOVE 手指 在屏幕上滑動 時(shí)觸發(fā),會會多次觸發(fā)。
ACTION_UP 手指 離開屏幕 時(shí)觸發(fā)。
ACTION_CANCEL 事件 被上層攔截 時(shí)觸發(fā)。
屏幕中的控件 原文鏈接

為了在屏幕中如何尋找合適的處理事件的控件,我們先來看下屏幕中都有什么控件。

假設(shè)我們寫了如下的一個(gè)布局:



    

        

    

    

View結(jié)構(gòu):

原文鏈接

上面的代碼運(yùn)行到界面上由圖中這幾部分組成:

可以看到在上面的View結(jié)構(gòu)中莫名多出來的兩個(gè)東西,PhoneWindow 和 DecorView ,這兩個(gè)我們并沒有在Layout文件中定義過,但是為什么會存在呢?

1. PhoneWindow
PhoneWindow是 Window 的唯一實(shí)現(xiàn)類,是所有視圖的最頂層容器,視圖的外觀和行為都?xì)w他管,不論是背景顯示,標(biāo)題欄還是事件處理都是他管理的范疇。
2. DecorView
DecorView是 PhoneWindow 的一個(gè)內(nèi)部類,就是跟在 PhoneWindow 身邊專業(yè)為 PhoneWindow 服務(wù)的,除了自己要干活之外,也負(fù)責(zé)消息的傳遞,PhoneWindow 的指示通過 DecorView 傳遞給下面的 View,而下面 View 的信息也通過 DecorView 回傳給 PhoneWindow。
事件分發(fā)流程

在如上圖View的樹形結(jié)構(gòu)中,事件發(fā)生時(shí),最先由Activity接收,然后再一層層的向下層傳遞,直到找到合適的處理控件。大致如下:

Activity -> PhoneWindow -> DecorView -> ViewGroup -> ... -> View

但是如果事件傳遞到最后的View還是沒有找到合適的View消費(fèi)事件,那么事件就會向相反的方向傳遞,最終傳遞給Activity,如果最后 Activity 也沒有處理,本次事件才會被拋棄:

Activity <- PhoneWindow <- DecorView <- ViewGroup <- ... <- View
Android中事件具體是怎樣進(jìn)行分發(fā)的 原文鏈接

當(dāng)事件發(fā)生時(shí),ViewGroup會在dispatchTouchEvent方法中先看自己能否處理事件,如果不能再去遍歷子View查找合適的處理控件。如果到最后result還是false,表示所有的子View都不能處理,才會調(diào)用自身的onTouchEvent來處理。

根據(jù)上面提到的原理,ViewGroup事件傳遞的偽代碼如下:

public boolean dispatchTouchEvent(MotionEvent ev) {
    boolean result = false;             // 默認(rèn)狀態(tài)為沒有消費(fèi)過

    if (!onInterceptTouchEvent(ev)) {   // 如果沒有攔截交給子View
        result = child.dispatchTouchEvent(ev);
    }

    if (!result) {                      // 如果事件沒有被消費(fèi),詢問自身onTouchEvent
        result = onTouchEvent(ev);
    }

    return result;
}

為了方便理解,這里貼出一張網(wǎng)上的別人的一張圖:

紅色箭頭方向表示事件分發(fā)方向。

綠色箭頭方向表示事件回傳方向。

上面的流程中存在部分不合理內(nèi)容,請大家選擇性接受。
事件返回時(shí) dispatchTouchEvent 直接指向了父View的 onTouchEvent 這一部分是不合理的,實(shí)際上它僅僅是給了父View的 dispatchTouchEvent 一個(gè) false 返回值,父View根據(jù)返回值來調(diào)用自身的 onTouchEvent。
ViewGroup 是根據(jù) onInterceptTouchEvent 的返回值來確定是調(diào)用子View的 dispatchTouchEvent 還是自身的 onTouchEvent, 并沒有將調(diào)用交給 onInterceptTouchEvent。

如果在遍歷過程中,發(fā)現(xiàn)了有可以處理事件的控件,就停止事件的傳遞,事件被消耗。

本文參考資料:
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開發(fā)藝術(shù)探索

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/73365.html

相關(guān)文章

  • 前端基礎(chǔ)進(jìn)階(十二):深入核心,詳解事件循環(huán)機(jī)制

    摘要:前端基礎(chǔ)進(jìn)階正是圍繞這條線索慢慢展開,而事件循環(huán)機(jī)制,則是這條線索的最關(guān)鍵的知識點(diǎn)。特別是中正式加入了對象之后,對于新標(biāo)準(zhǔn)中事件循環(huán)機(jī)制的理解就變得更加重要。之后全局上下文進(jìn)入函數(shù)調(diào)用棧。 showImg(https://segmentfault.com/img/remote/1460000008811705); JavaScript的學(xué)習(xí)零散而龐雜,因此很多時(shí)候我們學(xué)到了一些東西,但...

    whjin 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<