1. 程式人生 > >Android觸控事件傳遞機制,這一篇就夠了

Android觸控事件傳遞機制,這一篇就夠了

整個觸控事件牽涉到的是,Activity,View,ViewGroup三者的傳遞機制。
這個觸控事件就是從外層往內層一層層的傳遞。
整個傳遞機制,分為3個步驟:分發,攔截,和消費。

1. 觸控事件的型別

事件型別是MotionEvent類:看下最新的sdk29的原始碼,一堆的Action,我們常用的其實就3個,ACTION_DOWN,ACTION_MOVE,ACTION_UP。
Down和Up事件,是觸控過程中一定會發生的事件。Move事件看具體的情況。

2.事件傳遞的順序

從外層往內層一層層的傳遞,外層是那個,內層是那個?
我們從android系統的角度看。事件首先傳給的肯定是Activity,因為Activity的UI佈局,事物邏輯,作為底層來說,不知道,也並不關心。

所以只要把事件送到Activity層,就可以。
同樣的道理,事件先送到ViewGroup,然後在送到View。這樣從外層到內層的過程。
其實每一層都會對觸控事件有響應,這個事件是有具體的業務邏輯決定的,所以我們需要一些操作來控制這個事件的過程。
比如點選事件,假設點選了某個按鈕,這樣它的父ViewGroup要不要處理,頁面要不要處理,從表面來看他們都被點選了,從實際人們的經驗來看,
就是View被點選了,不需要ViewGroup和Activtiy後面2個事件觸發。
Activity->ViewGroup->ViewGroup...->View 整個事件流程傳遞就是這樣。
View->ViewGroup...->ViewGroup->Activity 這個就是事件的消費過程。

3.事件傳遞的3個階段

所以android把觸控事件傳遞分為3個步驟:分發,攔截,和消費。

3.1 分發

分發:事件分發對應著dispatchTouchEvent方法,在Android中,所有的觸控事件都是這個方法來分發的。

public boolean dispatchTouchEvent(MotionEvent ev)

3.1.1 Activity分發

分發是觸控事件首先到達。

  • 返回true,表示事件被消耗掉。不需要分發下去。消費了事件,後續的事件會繼續傳遞到這裡。
  • 返回false,表示事件被廢棄掉。因為dispatchTouchEvent是總入口,所以就算是false,後續事件還會出現。
  • 返回值是super.dispatchTouchEvent,事件繼續傳遞下去,這個是整個事件傳遞的中樞,從原始碼看,一切從這來開始,也從這裡結束。
    如果view hierarchy都不處理這個touch事件,就由Activity的onTouch事件來處理。可見上面第二節的結論是正確的。最先接收,最後處理。
/**
     * Called to process touch screen events.  You can override this to
     * intercept all touch screen events before they are dispatched to the
     * window.  Be sure to call this implementation for touch screen events
     * that should be handled normally.
     *
     * @param ev The touch screen event.
     *
     * @return boolean Return true if this event was consumed.
     */
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            onUserInteraction();
        }
        if (getWindow().superDispatchTouchEvent(ev)) {
            return true;
        }
        return onTouchEvent(ev);
    }

3.1.2VIewGroup分發

  • 返回true,表示事件被消耗掉。不需要分發下去。消費了事件,後續的事件會繼續傳遞到這裡。
  • 返回false,表示事件被廢棄掉。後續的其他事件不會被傳遞到這裡。
  • 返回值是super.dispatchTouchEvent,事件繼續傳遞下去,這個是整個事件傳遞的中樞,從原始碼看,ViewGroup的分發流程分以下幾步
    有攔截,攔截了touch事件,就走ViewGroup自己的onTouchEvent。
    沒有攔截,就找到觸控點的位置,上面是否有View,有就調view.dispatchTouchEvent,如果沒有,就直接交給ViewGroup處理。
    這裡還有一點,如果action_down已經處理了,後面action_up 和 action_move都使用相同的處理方式。

3.1.3 View的分發

View的分發,也許會覺得奇怪,分發給誰?
從原始碼看,2個途徑,onTouch listener,或者onTouchEvent。前者優先順序必後者高。

  • 返回true,表示事件被消耗掉。不需要分發下去。消費了事件,後續的事件會繼續傳遞到這裡。並且這裡會認為事件被View消費掉了,所以上層的VIewGroup不會收到要處理onTouchEvent的事件。
  • 返回false,表示事件被廢棄掉。後續的其他事件不會被傳遞到這裡。而且可以理解為,我這個View不想處理這個事件,所以ViewGroup會觸發onTouchEvent事件。
  • 返回值是super.dispatchTouchEvent
            ListenerInfo li = mListenerInfo;
            if (li != null && li.mOnTouchListener != null
                    && (mViewFlags & ENABLED_MASK) == ENABLED
                    && li.mOnTouchListener.onTouch(this, event)) {
                result = true;
            }

            if (!result && onTouchEvent(event)) {
                result = true;
            }

onTouch是否處理,return true,就表面被第三方處理了,不需要onTouchEvent來處理。不然就是onTouchEvent處理。

3.2 攔截

事件攔截對應onInterceptTouchEvent。事件是從外向內傳遞的,當事件在分發的過程中,要不要攔截,

public boolean onInterceptTouchEvent(MotionEvent ev)

有些情況下需要子View來響應,有些情況需要當前ViewGroup來處理。這個方法Activity沒有,只有ViewGroup才有。
這個簡單來說就是,是否需要分發事件給到子View,true就是不分發。

3.3 消費

其實dispatchTouchEvent也有消費的概念在裡面。
如果說分發的流程,是從外層到內層,
消費的流程正好相反,從內層到外層。

public boolean onTouchEvent(MotionEvent event) 
  • 返回true,消費事件,不在向外層傳遞
    -返回false,不消費事件,向外層傳遞
    -返回spuer.onTouchEvent,這裡會判斷是否是click事件。只有這個寫法才會觸發click事件。

4. 流程圖

5.總結

流程很複雜,每個部分返回不同的true/fase/super都會產生不同的流程結果。
事件分發流程:
從外層到內層分發,
從內層到外層消費。

dispatchTouchEvent 和onTouchEvent,返回true,代表由自己處理這個事情。阻斷後面的流程。
dispatchTouchEvent 和onTouchEvent,返回false,表示不由自己來處理這個事件,流程交由上一層級來處理。
dispatchTouchEvent 和onTouchEvent,返回spuer,就是上面的流程。

更多內容:demanmath
公共號:

相關推薦

Android觸控事件傳遞機制

整個觸控事件牽涉到的是,Activity,View,ViewGroup三者的傳遞機制。 這個觸控事件就是從外層往內層一層層的傳遞。 整個傳遞機制,分為3個步驟:分發,攔截,和消費。 1. 觸控事件的型別 事件型別是MotionEvent類:看下最新的sdk29的原始碼,一堆的Action,我們常用的其實就3個

Android音訊錄製、播放

github原始碼下載地址:https://github.com/geduo83/AudioRecorder csdn原始碼下載地址:https://download.csdn.net/download/geduo_83/10841496 音訊錄製、播放 最近在專案要用到錄音的功能,

關於Jvm類載入機制

前言 一個月沒更新了,這個月發生了太多的事情,導致更新的頻率大大降低,不管怎樣收拾心情,技術的研究不能落下! jvm作為每個java程式猿必須瞭解的知識,博主推薦一本書《深入理解Java虛擬機器》,以前博主在學校的時候看過幾遍,每一次看都有新的理解。加上工作了也有一年多的時間了,有必要好好總結一番~ 什麼是j

Android 屬性動畫框架 ObjectAnimator、ValueAnimator

前言 我們都知道 Android 自帶了 Roate Scale Translate Alpha 多種框架動畫,我們可以通過她們實現豐富的動畫效果,但是這些寬家動畫卻有一個致命的弱點,它們只是改變了 View 顯示的大小,而沒有改變 View 的響應區域。這時以 ObjectAnimator、ValueAni

自定義 Android 鐘表盤

關於本文:本文原先在我的 CSDN 部落格釋出(由圖片水印能發現),整理以往部落格過程中,發現當時總結的很仔細,所以將其遷移到這裡,希望對大家在自定義 View 方面,能有所幫助

萬字總結:學習MySQL優化原理

ade min() 全表掃描 搜索 財務 兼容 嵌套循環 很大的 完成 前言 說起MySQL的查詢優化,相信大家收藏了一堆奇技淫巧:不能使用SELECT *、不使用NULL字段、合理創建索引、為字段選擇合適的數據類型..... 你是否真的理解這些優化技巧?是否理解其背後的工

Elasticsearch入門

search 語義 瀏覽器 三種 http請求 機制 說明 pro .net 實時搜索引擎Elasticsearch Elasticsearch(簡稱ES)是一個基於Apache Lucene(TM)的開源搜索引擎,無論在開源還是專有領域,Lucene可以

解golang的不定參數(... parameters)

type col interface 原因 相同 tro fun cti func 在實際開發中,總有一些函數的參數個數是在編碼過程中無法確定的,比如我們最常用的fmt.Printf和fmt.Println: fmt.Printf("一共有%v行%v列\n", rows,

看懂Serverless

簽名 雲廠商 不能 處理 上傳 微服務架構 stateless 系統管理 服務 一、 無服務器(Serverless)計算是什麽雲計算湧現出很多改變傳統IT架構和運維方式的新技術,比如虛擬機、容器、微服務,無論這些技術應用在哪些場景,降低成本、提升效率是雲服務永恒的主題。

瞭解HTTP協議

1、HTTP協議簡介 1.1、HTTP協議是超文字傳輸協議的簡稱,工作於應用層,用於從伺服器傳輸超文字到本地瀏覽器。HTTP協議本身是一種無狀態的,也沒法自己傳輸資料,底層的資料傳輸協議是TCP協議。HTTP協議工作於客戶端-服務端架構為上。瀏覽器作為HTTP客戶端通過URL向HTTP服務端

掌握react

react眾所周知的前端3大主流框架之一,由於出色的效能,完善的周邊設施風頭一時無兩。本文就帶大家一起掌握react。 jsx語法 前端MVVM主流框架都有一套自己的模板處理方法,react則使用它獨特的jsx語法。在元件中插入html類似的語法,簡化建立view的

JVM和垃圾回收面試入門

前些天在 google 上搜索了一些JVM的參考資料,偶然發現了一篇文章,如獲至寶,簡單易懂而且相對全面的JVM和垃圾回收介紹寫得非常的棒,因此一直儲存著,今天有時間特意翻譯了一下。本人水平有限,但是遇到好文章希望可以與更多的人分享,特此釋出此文。 英文OK的話

學會資料庫讀寫分離、分表分庫——用Mycat

轉:     https://www.cnblogs.com/joylee/p/7513038.html 系統開發中,資料庫是非常重要的一個點。除了程式的本身的優化,如:SQL語句優化、程式碼優化,資料庫的處理本身優化也是非常重要的。主從、熱備、分表分庫等都是系統

瞭解golang的不定引數(... parameters)

在實際開發中,總有一些函式的引數個數是在編碼過程中無法確定的,比如我們最常用的fmt.Printf和fmt.Println: fmt.Printf("一共有%v行%v列\n", rows, cols) fmt.Println("共計大小:", size) 當你需要實現類似的介面時,就需要我們的不定引數出場

深入Babel

前言 既然標題說了是深入Babel,那我們就不說Babel各種用法了,什麼babel-core,babel-runtime,babel-loader……如果你想了解這一部分內容,這類文章很多,推薦最近看到的一篇:一口(很長的)氣了解 babel,可以說是相當詳實完備了。 言歸正傳,這篇文章主要是去了解一下

國家密集釋出工業網際網路相關資訊2018年工業猿們準備好嗎!附:相關連結。

       有時候想想工業猿們的確很辛苦,跑工業現場,環境惡劣;需要分析、軟體開發、安裝實施、商務三陪及回款.....一身扛,.這才是全棧人才吧;要說到回報,那尼麻才是我們痛心的地方,聽到網際網路公司的“人才”們談薪水都是**K、**K......,感覺猿類裡也分三六九等呀,那心情好比現在北京大約在冬季清理

學習Python3 程序

第一種方式:使用os模組中的fork方式實現多程序 輸出結果: 第二種方法:使用multiprocessing模組建立多程序 輸出結果是:   輸出結果是: # Queue程序間通訊 Queue程序間通訊 輸出

6000+個景點資料視覺化國慶出遊避免擁擠

歡迎關注天善智慧,我們是專注於商業智慧BI,人工智慧AI,大資料分析與挖掘領域的垂直社群,學習,問答、求職一站式搞定! 對商業智慧BI、大資料分析挖掘、機器學習,python,R等資料領域感興趣的同學加微信:tsaiedu,並註明訊息來源,邀請你進入資料愛好者交流群,資料愛好者們都

看懂中國人工智慧格局

2016年以來,人工智慧成為了非常熱門的概念。阿爾法機器人上春晚,阿爾法狗大戰李世石等事件,把機器人帶進了公眾的視野,甚至引發了一些機器人取代人、危害人等消極觀點。儘管如此,恰逢Fintech金融科技浪潮的來臨,人工智慧已成了各個細分領域的“標配”。科技公司不沾個“人工智慧”的詞兒,都不好意思出來混。一時間市

安卓ServiceManager啟動:徹底理解ServiceManager啟動流程

基於Android 6.0的原始碼剖析, 本文詳細地講解了ServiceManager啟動流程 framework/native/cmds/servicemanager/ - service_manager.c - binder.c kernel/driv