九九99精品-九九99靖品-九九99九九视频在线观看-九九99九九在线精品视频-曰韩一级-曰韩一级毛片

Android觸摸事件的響應(yīng)機(jī)制

作者: Touchscreen     時(shí)間:2015-06-17     源于:科技快報(bào)    總點(diǎn)擊:
【導(dǎo)讀】:在用戶的一次單手指觸摸屏幕過程中,簡單的講,會(huì)按順序產(chǎn)生一個(gè)ACTION_DOWN,若干個(gè)ACTION_MOVE,和一個(gè)ACTION_UP,我們下面的討論也會(huì)基于這個(gè)簡單case。

    北京時(shí)間06月17日消息,中國觸摸屏網(wǎng)訊,用戶觸摸屏幕所產(chǎn)生的Touch Event在Android里是用一個(gè)MotionEvent對(duì)象來傳遞和處理的,我們最關(guān)注的是MotionEvent里的action,可以看到有ACTION_DOWN, ACTION_UP,ACTION_MOVE,ACTION_CANCEL,ACTION_POINTER_DOWN,ACTION_POINTER_UP等等很多種,在這里面最需要關(guān)注的是ACTION_DOWN和ACTION_UP,它們一個(gè)代表了用戶按壓動(dòng)作的開始,一個(gè)代表了用戶按壓動(dòng)作的結(jié)束,其他的一些ACTION基本都是發(fā)生在這2個(gè)ACTION之間的(ACTION_CANCEL等特殊的暫不討論)。

    本文來自:http://www.zc28898.cn/touchscreen/news/front/201506/17-36507.html

在用戶的一次單手指觸摸屏幕過程中,簡單的講,會(huì)按順序產(chǎn)生一個(gè)ACTION_DOWN,若干個(gè)ACTION_MOVE,和一個(gè)ACTION_UP,我們下面的討論也會(huì)基于這個(gè)簡單case。

觸摸事件的傳遞處理順序

一個(gè)觸摸事件首先是在硬件層面觸發(fā),然后逐層傳遞到軟件直至我們的app,前面的細(xì)節(jié)一般來說不用了解,我們討論的事件入口從Activity開始。

籠統(tǒng)的說(實(shí)際上細(xì)節(jié)有所不同,下面會(huì)提到)

觸摸事件的傳遞順序是:

Activity -> 當(dāng)前活動(dòng)窗口(PhoneWindow) -> 窗口的Top-Level View(DecorView) -> 各級(jí)ViewGroup (如各種Layout) -> ... -> 各級(jí)ViewGroup -> 葉子節(jié)點(diǎn) View

而觸摸事件的處理順序則剛好相反:

葉子節(jié)點(diǎn) View -> 各級(jí)ViewGroup -> ... -> 各級(jí)ViewGroup -> (Window和DecorView只有分發(fā)沒有處理) -> Activity

當(dāng)葉子節(jié)點(diǎn)View接受到事件之后,會(huì)試圖做出處理,如果它處理了,則上面各層不再處理,如果它沒有處理則往上由它的父ViewGroup處理,這樣逐層向上按順序試圖處理,直到Activity。

分發(fā)和處理的關(guān)鍵函數(shù)

從上面籠統(tǒng)提到的事件分發(fā)處理順序可以看到,關(guān)鍵的分發(fā)處理集中在Activity,ViewGroup和View中,那么對(duì)于它們來說,有如下幾個(gè)分發(fā)和處理的關(guān)鍵函數(shù),這里先做一個(gè)簡單介紹,后續(xù)再做詳細(xì)說明。

1,boolean dispatchTouchEvent(MotionEvent event)

這個(gè)函數(shù)是最關(guān)鍵的分發(fā)處理函數(shù),里面既包含了分發(fā)的邏輯,又包含了對(duì)處理的邏輯調(diào)用

分發(fā)邏輯:這個(gè)函數(shù)會(huì)先調(diào)用子view的dispatchTouchEvent進(jìn)行分發(fā)

處理邏輯:如果子view沒有對(duì)事件進(jìn)行消化處理的話,這個(gè)函數(shù)就會(huì)調(diào)用本UI組件的處理函數(shù)如onTouchEvent

函數(shù)返回值表示這個(gè)觸摸事件是否被當(dāng)前這個(gè)UI組件(Activity/ViewGroup/View)消化處理了

2,boolean onTouchEvent(MotionEvent event)

這個(gè)函數(shù)是UI組件自己實(shí)現(xiàn)用來響應(yīng)處理觸摸事件的

函數(shù)返回值表示這個(gè)觸摸事件是否被當(dāng)前這個(gè)UI組件(Activity/ViewGroup/View)消化處理了

3,View.OnTouchListener: boolean onTouch(View v, MotionEvent event)

這個(gè)函數(shù)不是Activity/ViewGroup/View本身的響應(yīng)處理函數(shù),而是一個(gè)Listener的響應(yīng)處理函數(shù)

需要給View通過setOnTouchListener來設(shè)置Listener以使得這個(gè)onTouch函數(shù)能夠起作用

Activity沒有setOnTouchListener

函數(shù)返回值表示這個(gè)觸摸事件是否被當(dāng)前這個(gè)UI組件(Activity/ViewGroup/View)消化處理了

4,ViewGroup: boolean onInterceptTouchEvent(MotionEvent event)

這個(gè)函數(shù)表明是否要攔截這個(gè)事件,前面提到過事件的分發(fā)順序是在View tress里從根到葉子逐層分發(fā),處理則是反向的從葉子到根逐層處理,onInterceptTouchEvent如果返回true,則表示我這一層要攔截這個(gè)事件自己進(jìn)行處理了,不要把它分發(fā)到子View里

這個(gè)函數(shù)只有ViewGroup含有,View沒有,因?yàn)閂iew已經(jīng)是葉子節(jié)點(diǎn)了,沒有子View了

這個(gè)函數(shù)默認(rèn)是返回false的,一般不要輕易o(hù)verride它,因?yàn)槌R?guī)來講是應(yīng)該由子View先響應(yīng)處理的

分發(fā)和處理的細(xì)節(jié)流程

ACTION_DOWN的處理

前面說過ACTION_DOWN是一個(gè)觸摸動(dòng)作的起始,所以對(duì)ACTION_DOWN的處理和對(duì)其他事件的處理在細(xì)節(jié)上是有不同的,各個(gè)UI組件對(duì)于ACTION_DOWN事件的處理流程可以看到如下:

(注意這里 view 表示一個(gè)視圖組件,它可以是一個(gè) View 也可以是一個(gè) ViewGroup)

Activity -> dispatchTouchEvent:

通過getWindow().superDispatchTouchEvent(event)把事件分發(fā)到當(dāng)前活動(dòng)窗口(PhoneWindow),之后是 窗口的Top-Level View(DecorView),調(diào)用了DecorView的dispatchTouchEvent,DecorView繼承自ViewGroup,所以這里實(shí)際上就進(jìn)入了ViewGroup層面的dispatchTouchEvent

如果superDispatchTouchEvent最終返回true(即下層的某個(gè)ViewGroup或者View消化處理了該函數(shù),dispatchTouchEvent返回true),則直接返回

如果返回值為false,則調(diào)用Activity的onTouchEvent對(duì)事件進(jìn)行處理

ViewGroup -> dispatchTouchEvent:

首先是檢查本view里是否保存了一個(gè)motion target(步驟4提到了怎么設(shè)置motion target),如果有則清除它

然后是調(diào)用onInterceptTouchEvent看這個(gè)事件是否需要被自己攔截,如果返回true,則直接進(jìn)入步驟7開始自己處理事件的流程

如果返回false,則需要遍歷所有的子view,遍歷的順序是:

首先按照Z-order

在同一Z值下如果可以的話按照子view的drawing order,這里的drawing order需要ViewGroup的子類override了getChildDrawingOrder才會(huì)實(shí)際生效

遍歷子view的時(shí)候,如果這個(gè)觸摸事件發(fā)生的位置在這個(gè)view的視覺范圍以內(nèi),那么就調(diào)用child.dispatchTouchEvent將事件分發(fā)給這個(gè)子view,如果這個(gè)子view消化處理了這個(gè)事件(即dispatchTouchEvent返回true),本view會(huì)將該子view賦值給一個(gè)表明motion target的變量,且此時(shí)跳出循環(huán)

循環(huán)遍歷結(jié)束后,如果有子view處理了該事件(即motion target不為空),則返回true表明此事件已經(jīng)被處理

如果沒有任何一個(gè)子view處理了該事件(即motion target不為空),則本view需要進(jìn)行處理,進(jìn)入步驟6

查看當(dāng)前view是否注冊了OnTouchListener,如果有,則調(diào)用該listener的onTouch函數(shù)來處理事件,如果onTouch返回true表示消化處理了該事件,則直接返回true

如果onTouch返回false表示沒有處理,則繼續(xù)調(diào)用本view的onTouchEvent函數(shù)來處理事件,這里會(huì)返回onTouchEvent的返回值

View -> dispatchTouchEvent:

查看當(dāng)前view是否注冊了OnTouchListener,如果有,則調(diào)用該listener的onTouch函數(shù)來處理事件,如果onTouch返回true表示消化處理了該事件,則直接返回true

如果onTouch返回false表示沒有處理,則繼續(xù)調(diào)用本view的onTouchEvent函數(shù)來處理事件,這里會(huì)返回onTouchEvent的返回值

其他ACTION的處理

上面說了ACTION_DOWN的處理,那ACTION_DOWN后續(xù)的ACTION_MOVE,ACTION_UP之類的事件又是怎么處理的呢?它們的處理方式略有不同:

在Activity層面來看,它們的處理和ACTION_DOWN沒有區(qū)別。

在ViewGroup層面來看,處理開始有了差異:

ViewGroup -> dispatchTouchEvent:

檢查當(dāng)前view在之前處理ACTION_DOWN(ACTION_MOVE,ACTION_UP之類的事件一定是有一個(gè)配對(duì)的ACTION_DOWN事件在前面發(fā)生)的時(shí)候是否已經(jīng)設(shè)置了一個(gè)motion target

如果有這個(gè)target,那么表明之前的ACTION_DOWN事件就是由該子view處理的,此時(shí)直接調(diào)用motion_target.dispatchTouchEvent

如果沒有這個(gè)target,那么表明之前的ACTION_DOWN沒有任何一個(gè)子view處理,那么后續(xù)這些事件也不要發(fā)給子view了,直接自己處理,進(jìn)入步驟4

查看當(dāng)前view是否注冊了OnTouchListener,如果有,則調(diào)用該listener的onTouch函數(shù)來處理事件,如果onTouch返回true表示消化處理了該事件,則直接返回true

如果onTouch返回false表示沒有處理,則繼續(xù)調(diào)用本view的onTouchEvent函數(shù)來處理事件,這里會(huì)返回onTouchEvent的返回值

注意整個(gè)流程中都跳過了onInterceptTouchEvent的攔截

在View層面來看,處理方式也是一樣的。

所以這里可以看到的現(xiàn)象就是:ACTION_DOWN被誰處理了,后續(xù)的ACTION_MOVE,ACTION_UP等事件最終也會(huì)交由誰處理。

onTouchEvent() or OnTouchListener.onTouch()?

從上面的內(nèi)容可以看出來,我們要想對(duì)一個(gè)觸摸事件進(jìn)行響應(yīng),可以在view的onTouchEvent()函數(shù)里處理,也可以給view設(shè)置一個(gè)OnTouchListener然后在listener的onTouch()函數(shù)里處理,那么它們有些什么區(qū)別?我們應(yīng)該怎么選擇呢?

首先看區(qū)別:

onTouchEvent()是View自己的函數(shù),對(duì)于我們來說無法override 各種View或者ViewGroup的onTouchEvent()函數(shù),只能是在自己自定義的view里面實(shí)現(xiàn)override;而OnTouchListener的onTouch()是可以對(duì)任何View/ViewGroup起作用的,我們只需要在代碼里為該View/ViewGroup加一個(gè)listener就行

OnTouchListener的onTouch()的執(zhí)行順序在view的onTouchEvent()之前,如果在onTouch()函數(shù)里面響應(yīng)完了觸摸事件并返回true之后,onTouchEvent()是不會(huì)被調(diào)用的

知道了區(qū)別,那么我們就可以輕易的做出選擇了(只是一家之言,歡迎各種不同意見):

OnTouchListener的onTouch()基本上是萬能的,任何時(shí)候都可以用它,所以大部分時(shí)候直接用它就行了

在自定義view里面,如果出于代碼結(jié)構(gòu)和功能清晰的目的,可以使用onTouchEvent()

 


    觸摸屏與OLED網(wǎng)推出微信公共平臺(tái),每日一條微信新聞,涵蓋觸摸屏材料、觸摸屏設(shè)備、觸控面板行業(yè)主要資訊,第一時(shí)間了解觸摸屏行業(yè)發(fā)展動(dòng)態(tài)。關(guān)注辦法:微信公眾號(hào)“i51touch” 或微信中掃描下面二維碼關(guān)注,或這里查看詳細(xì)步驟
相關(guān)閱讀:3D打印    模具產(chǎn)業(yè)    微鑄鍛技術(shù)    石墨烯    OLED面板    夏普    iPhone 8    半導(dǎo)體    蘋果    
關(guān)于我們 | 廣告服務(wù) | 聯(lián)系我們 | 版權(quán)聲明 | 隱私政策 | 網(wǎng)站地圖 | 友情鏈接 | 歡迎投稿 | 加入收藏 | 意見反饋 | 經(jīng)銷商加入
網(wǎng)站廣告、經(jīng)銷商加盟、觸摸屏軟件銷售: 028-85108892 13183843395 028-66219290 聯(lián)系人: 張小姐 產(chǎn)品購買聯(lián)系方式如下:
地址:成都市高升橋東路2號(hào)高盛中心1109室 電話: 028-85108892 13183843395 028-66219290
版權(quán)所有 Copyright(C) 2003-2015 All rights reserved 中國觸摸屏網(wǎng) 電子郵件: 51touch@126.com touch8@gmail.com
業(yè)務(wù)合作QQ:觸摸屏技術(shù),觸摸屏報(bào)價(jià),觸摸屏軟件咨詢 43361182 觸摸屏軟件制作與技術(shù)支持:觸摸屏軟件,觸摸查詢系統(tǒng),觸摸查詢軟件 893008608 媒體合作QQ: 893008608

2000人超級(jí)QQ觸摸屏群:59897879 171220106


分享到