android觸摸消息的派發過程

1.觸摸消息是消息獲取模塊直接派發給應用程序的。
2.觸摸消息在處理時, 需要根據觸摸坐標計算該消息應該派發給哪個View/ViewGroup, 在案件取消處理中不存在 該計算過程。
3.沒有類似”系統按鍵”的”系統觸摸鍵”, 應用程序可完全控制觸摸行為。
4.子視圖優先父視圖處理消息, 即首先是子視圖處理該消息,只有當子視圖消耗該消息時, 父視圖才有機會處理 該消息。
觸摸消息總體派發過程
1.進行物理像素到邏輯像素的轉換。
2.如果是DOWN消息, 調用ensureTouchMode(true)函數則進入觸摸模式,與之相反的是”非觸摸模式”,即按鍵模式。
3.將屏幕坐標轉換到視圖坐標。
4.調用mView.dispathTouchEvent()將消息派發給根視圖,該函數內部會繼而將消息派發到整個View樹。
5.如果以上根視圖以及其所有子視圖都沒有消耗該消息,最后處理屏幕邊界偏移。屏幕邊界偏移在程序中用英文edge slop表示,它的作用是當用戶正好觸摸到屏幕邊界時,系統自動對原始消息進行一定的偏移,然后在新的偏移后的位置上尋找是否有匹配的視圖,如果有則將消息派發到該視圖。
根視圖內部消息派發過程
首先來看mView.dispatchTouchEvent()的派發過程。該函數是在ViewRoot中調用的,mView的類型可能有兩種情況,對于應用窗口而言,mView是一個PhoneWindow中的DecorView類型,對于非應用窗口而言,mView是一般的ViewGroup類型。
在DecorView中,首先判斷是否存在Callback對象,它和按鍵消息派發時的Callback對象一樣,就是Activity類。如果沒有Callback對象,則直接調用DecorView基類ViewGroup中的dispatchTouchEvent()函數。
在Activity中,dispatchTouchEvent()的過程如下。
1、如果ACTION_DOWN消息,則調用onUserInteraction()。
2、調用所包含的Window對象的superDispatchTouchEvent()。
3、如果Window類沒有消耗該消息,則調用onTouchEvent()。
下面看看Window類中的superDispatchTouchEvent()。此時Window類的實現就是PhoneWindow類,該函數繼而調用mDecor的superDispatchTouchEvent(),而在DecorView的該函數中又調用super.dispatchTouchEvent,即ViewGroup的dispatchTouchEvent函數。注意這里的調用過程,一般的消耗處理流程是當上一步沒有消耗消息時才執行下一個處理邏輯,而在跟視圖DecorView中,則是當沒有Callback時才調用ViewGroup的消息處理邏輯,而不是當Callback沒有消耗消息時才調用ViewGroup的消息處理邏輯,原因就是Callback本身就會調用ViewGroup的消息處理邏輯。
ViewGroup的內部消息派發過程
ViewGroup內部的處理邏輯也采用遞歸方式,但與按鍵處理的遞歸有所不同。觸摸消息處理中首先會把消息派發給View樹中最后一個子視圖,如果子視圖沒有消耗該消息,才遞歸派發給其父視圖,而在按鍵消息處理時,遞歸的過程正好相反。
1、將布局左邊轉化為視圖坐標。
為什么要轉換呢?因為接下來要判斷該坐標落到了該ViewGroup中的哪個子視圖中,子視圖的位置都是相對于該ViewGroup的視圖坐標的。
2、處理DOWN消息,其作用是判斷該視圖坐標落到了哪個子視圖中。
(1)首先判斷ViewGroup本身是否被禁止獲取Touch消息,如果沒有禁止,并且回調函數onInterceptTouchEvent()中沒有消耗該消息,則意味著該消息可以傳遞給子視圖。如果子視圖消耗了該DOWN消息,則直接返回true。
(2)開始尋找子視圖。調用child.getHitRect(frame)函數獲取該子視圖在父視圖中的布局坐標,即該ViewGroup為該child分配的位置是什么,這個位置相對于該child來講是布局坐標,而相對于ViewGroup來講卻是視圖坐標,參數frame是執行完畢后的位置輸出矩形。得到位置后,就可以調用frame.contain()方法判斷該消息位置是否被包含到了該child中,如果包含,并且該child也是一個ViewGroup,則準備遞歸調用該child的dispatchTouchEvent(),在調用之前,首先需要把坐標重新轉換到child的坐標系中。
(3)完成了遞歸操作錢的坐標轉換工作,接下來判斷該child是否是ViewGroup類。如果是就遞歸調用到ViewGroup的dispatchTouchEvent(),重新從第一步開始執行,如果child不是ViewGroup,而是一個View,則意味著遞歸調用的結束。
3、如果是UP活著CANCEL消息,則消除mGroupFlags中的FLAG_DISALLOW_INTERCEPT標識,即允許該ViewGroup截獲消息。
4、判斷target變量是否為空。空代表了所有的子窗口沒有消耗該消息,所以該ViewGroup本身需要處理該消息。在第二步中,如果匹配到某個child, 并且該child消耗了消息后,會將該child賦值給父視圖中的mMotionTarget變量。在該步中,首先要還原消息的原始位置,因為在第二步中,為了判斷子視圖是否包含該消息中的位置,對位置進行了從布局坐標到視圖坐標的轉換,而此時則需要把視圖坐標重新轉換為布局坐標,因為接下來要調用super.dispatchTouchEvent(),即View類的該函數。View類中處理該函數時,需要布局坐標。轉換之后,直接調用super.dispatchTouchEvent(),并返回其執行結果,該函數內部僅僅是回調onTouchEvent(),調用之前先判斷mPrivateFlags中是否包含CANCEL_NEXT_UP_EVENT標識,該表示一般情況下不會存在,如果存在,則將消息的action類型改為ACTION_CANCEL。
5、處理target存在,并且變量disallowInercept為false;即允許截獲,在默認況下ViewGroup都是允許截獲消息的,只有當該ViewGroup的子視圖調用父視圖的requestDisallowInterceptTouchEvent()函數時,方可禁止父視圖再次截獲消息。但每次UP消息或者CANCEL消息之后,該Viewgroup又會重新截獲信息。注意,在本步中,如果不允許截獲消息,那么也就不會調用onInterceptTouchEvent()函數了,如果允許,并且onTerceptTouchEvent()消耗了該消息,才執行本步的操作。
6、在大多數情況下都會執行到該步,即target存在,并且ViewGroup本身不允許截獲消息或者允許截獲但是卻沒有消耗消息,于是調用target.dispatchTouchEvent()把該消息繼續交給目標視圖處理。在調用該函數前需要檢查target中是否聲明過要取消隨后的消息,即mPrivateFlags中包含CANCEL_NEXT_UP_EVENT,如果是,則把消息action值修改為CANCEL,置空mMotionTarget變量,因為target不想處理接下來的消息,那么就可以認為沒有target了。
以上就是Touch消息在ViewGroup內部的遞歸和派發,在這里注意區分onInterceptTouchEvent()和onTouchEvent()。
onInterceptTouchEvent()是在ViewGroup中定義的,即只有ViewGroup的子類能夠重載該方法。而onTouchEvent()函數有兩個定義,一個是在View類中定義的,所有View類的子類都可以重載該方法,包括ViewGroup,另一個是在Activity中定義的,用戶Activity可以重載該函數。View系統的消息處理機制中,會先執行視圖內部的onTouchEvent,如果沒有處理,才會調用Activity中的onTouchEvent()。
另外,對于ViewGroup而言,在一般情況下會先調用onInterceptTouchEvent(),只有當該函數沒有消耗掉消息,并且其包含的子視圖也沒有消耗掉該消息時,才會執行該ViewGroup的onTouchEvent()。而對于View而言,沒有onInterceptTouchEvent()被調用。但并不是所有的消息處理過程都是先調用onInterceptTouchEvent(), 只有兩種情況才會調用到onInterceptTouchEvent()。
1.即在以上第2步驟中,當時DOWN消息,并且ViewGroup允許截獲消息時。
2.即在以上第5步驟中,當ViewGroup中存在target對象,并且允許截獲消息時。
View內默認消息派發過程
1、調用onFilterTouchEventForSecurity() 處理窗口處于模糊顯示狀態下的消息。所謂的模糊顯示是指,應用程序可以設置當前窗口為模糊狀態,此時窗口內部的所有視圖將顯示為模糊效果。這樣做的目的是為了隱藏窗口中的內容,對于其中各個視圖而言,可以設置該視圖的FILTER_TOUCHES_WHEN_OBSCURED標識,如果存在該標識,則意味著用戶希望不要處理該消息。
2、回調視圖監聽者的onTouch()函數,如果監聽者消耗了該消息,則直接返回。
3、調用onTouchEvent(),應用程序可以重載該函數,但如果沒有重載的話,該函數內部有默認的執行方式,默認的執行流程如下:
(1)判斷該視圖是否為disable狀態,如果是,什么都不做,返回true,即消耗該消息
(2)處理消息代理TouchDelegate。所謂的消息代理是指,可以給某個View指定一個消息處理代理,當View收到消息時,首先將該消息派發給其代理進行處理。如果代理內部消耗了該消息,則View不需要再進行任何處理;如果代理沒有處理,則View繼續按照默認的邏輯進行處理。該類的目的是為了擴大點擊區。(沒有實現)
(3)判斷該視圖是否是可以點擊的,如果不可點擊,則直接返回false,即不處理該消息。否則,真正開始執行觸摸消息的默認處理邏輯,該邏輯中分別處理了ACTION_DOWN、MOVE和UP消息,
1??在ACTION_DOWN消息中,給mPrivateFlags變量添加PRESSED標識,并將變量mHasPerformLongPress置為false,然后啟動tap監測,即發送一個異步延遲消息,延遲時間為ViewConfigration.getTapTimeout()。
2??對于觸摸消息而言,消息本身沒有repeat的屬性,這與按鍵消息不同,一次觸摸消息只有一個DOWN消息,接下來就是連續的MOVE消息,并最終以UP消息結束。
3??處理ACTION_UP消息,代碼中判斷該UP消息是發生在哪一個檢測時間段中,并據此進行不同的處理。
4、處理ACTION_CANCEL消息,這里只需要清除PRESSED標識,并改變視圖狀態,然后再關閉tap檢測即可。
至此Touch消息的一次處理過程就結束了。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/389168.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/389168.shtml
英文地址,請注明出處:http://en.pswp.cn/news/389168.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

python 交互式流程圖_使用Python創建漂亮的交互式和弦圖

python 交互式流程圖Python中的數據可視化 (Data Visualization in Python) R vs Python is a constant tussle when it comes to what is the best language, according to data scientists. Though each language has it’s strengths, R, in my opinion has one cutting-edg…

機器學習解決什么問題_機器學習幫助解決水危機

機器學習解決什么問題According to Water.org and Lifewater International, out of 57 million people in Tanzania, 25 million do not have access to safe water. Women and children must travel each day multiple times to gather water when the safety of that water …

遞歸原來可以so easy|-連載(3)

本期我們再通過幾個例子,加深遞歸的理解和熟練度。 上期有一個練習題:用遞歸逆序輸出一個包含整型數據的鏈表。 先完成這個練習題。 對于程序員來說,代碼是最好的溝通工具,什么都不說,上代碼: public class…

Viewport3D 類Viewport3D 類Viewport3D 類

.NET Framework 類庫Viewport3D 類更新:2007 年 11 月為三維可視內容提供呈現圖面。命名空間: System.Windows.Controls程序集: PresentationFramework(在 PresentationFramework.dll 中)用于 XAML 的 XMLNS&#xf…

升級android 6.0系統

How to Fix errors by manually flashing Marshmallow update 鏡像下載for nexus Factory image Step 1: Download the [Marshmallow factory image](http://www.theandroidsoul.com/download-mra58k-android-6-0-marshmallow-update-released-for-nexus-5-nexus-6-nexus-9-n…

AGC 022 B - GCD Sequence

題面在這里&#xff01; 鍛煉腦子的小構造題。。。 一開始被 a[]<30000 且 序列 gcd 1所困擾&#xff0c;但是發現這并沒有什么&#xff0c;因為我接下來發現了一種總是能構造出 序列和是6的倍數的方案。 首先如果 n3 的話輸出樣例&#xff0c;因為只有這種情況沒法用我的方…

最接近原點的 k 個點_第K個最接近原點的位置

最接近原點的 k 個點In this article, I will be explaining to you one of the problems that you may find when tackling questions in data structures and algorithm. You will need some basic knowledge of data structures in order to understand the optimized solut…

網絡瀏覽器如何工作

Behind the scenes of modern Web Browsers現代Web瀏覽器的幕后花絮 The Web Browser is inarguably the most common portal for users to access the web. The advancement of the web browsers (through the series of history) has led many traditional “thick clients”…

讓自己的頭腦極度開放

為什么80%的碼農都做不了架構師&#xff1f;>>> 一. 頭腦封閉和頭腦開放 頭腦封閉 你是否經常有這樣的經歷&#xff0c;在一次會議或者在一次小組討論時&#xff0c;當你提出一個觀點而被別人否定時&#xff0c;你非常急迫地去反駁別人&#xff0c;從而捍衛自己的尊…

簡介DOTNET 編譯原理 簡介DOTNET 編譯原理 簡介DOTNET 編譯原理

簡介DOTNET 編譯原理 相信大家都使用過 Dotnet &#xff0c;可能還有不少高手。不過我還要講講Dotnet的基礎知識&#xff0c;Dotnet的編譯原理。 Dotnet是一種建立在虛擬機上執行的語言&#xff0c;它直接生成 MSIL 的中間語言&#xff0c;再由DotNet編譯器 JIT 解釋映象為本機…

RecyclerView詳細了解

關于RecyclerView大家都不陌生了&#xff0c;它的使用也越來越受歡迎&#xff0c;現在總體了解一下RecyclerView的作用&#xff0c;為什么會有RecyclerView呢&#xff0c;我用ListView也能干所有的事情啊&#xff0c;尺有所短&#xff0c;寸有所長&#xff0c;先來看看Recycler…

案例與案例之間的非常規排版

In 1929 the Cond Nast publishing group brought Russian-born Mehemed Fehmy Agha—who had been working for the German edition of Vogue magazine—to America as art director for House & Garden, Vanity Fair, and the senior edition of Vogue.1929年&#xff0c…

熊貓分發_熊貓新手:第二部分

熊貓分發This article is a continuation of a previous article which kick-started the journey to learning Python for data analysis. You can check out the previous article here: Pandas for Newbies: An Introduction Part I.本文是上一篇文章的延續&#xff0c;該文…

淺析微信支付:申請退款、退款回調接口、查詢退款

本文是【淺析微信支付】系列文章的第八篇&#xff0c;主要講解商戶如何處理微信申請退款、退款回調、查詢退款接口&#xff0c;其中有一些坑的地方&#xff0c;會著重強調。 淺析微信支付系列已經更新七篇了喲&#xff5e;&#xff0c;沒有看過的朋友們可以看一下哦。 淺析微信…

view工作原理-計算視圖大小的過程(onMeasure)

view的視圖有兩種情況&#xff1a; 內容型視圖&#xff1a;由視圖的內容決定其大小。圖形型視圖&#xff1a;父視圖為view動態調整大小。 ### measure的本質 把視圖布局使用的“相對值”轉化成具體值的過程&#xff0c;即把WRAP_CONTENT,MATCH_PARENT轉化為具體的值。 measur…

[轉載]使用.net 2003中的ngen.exe編譯.net程序

ngen.exe程序為.net 2003自帶&#xff0c; 在&#xff1a;/windows/microsoft.net/framework/v1.1.4322目錄下ngen.exe ngen能把.net框架的東西編譯成機器碼.... 網友&#xff1a;Visual Studio .NET 2003程序的運行速度怎么樣&#xff0c;我有一個感覺&#xff0c;V…

基于Redis實現分布式鎖實戰

背景在很多互聯網產品應用中&#xff0c;有些場景需要加鎖處理&#xff0c;比如&#xff1a;秒殺&#xff0c;全局遞增ID&#xff0c;樓層生成等等。大部分的解決方案是基于DB實現的&#xff0c;Redis為單進程單線程模式&#xff0c;采用隊列模式將并發訪問變成串行訪問&#x…

數據分析 績效_如何在績效改善中使用數據分析

數據分析 績效Imagine you need to do a bank transaction, but the website is so slow. The page takes so much time to load, all you can see is a blue circle.想象您需要進行銀行交易&#xff0c;但是網站是如此緩慢。 該頁面需要花費很多時間來加載&#xff0c;您只能看…

隱私策略_隱私圖標

隱私策略During its 2020 Worldwide Developers Conference, Apple spent time on one of today’s hottest topics — privacy. During the past couple of years, Apple has been rolling out various public campaigns aiming to position itself as a company that respect…

Java中的數組

一、數組的定義type[] arrayName;type arrayName[]; 推薦第一種 二、數組的初始化 含義&#xff1a;所謂的初始化&#xff0c;就是為數組的數組元素分配內存空間&#xff0c;并為每個數組元素賦初始值 &#xff08;1&#xff09;靜態初始化&#xff1a;arrayName new type[…