




下載本文檔
版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】Android中怎么實(shí)現(xiàn)事件分發(fā)和處理
這期內(nèi)容當(dāng)中在下將會(huì)給大家?guī)?lái)有關(guān)Android中怎么實(shí)現(xiàn)事件分發(fā)和處理,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲?;A(chǔ)儲(chǔ)備View、MotionEvent我們都能詳細(xì)地說(shuō)出Android的四大組件:Activity,Service,ContentProvider和BoardcastReceiver,但是四大組件之外,我們用到也很多的是什么,其中肯定包括View,View是用戶跟程序溝通的入口,也是程序展現(xiàn)給用戶信息的窗口。關(guān)于View,一些基礎(chǔ)屬性還是要了解的,left,top,right,bottom,分別代表了view的左上角和右下角分別相對(duì)x軸,y軸的坐標(biāo),而且view的getWidth和getHeight的值都是通過(guò)這四個(gè)值算得,而且在Android3.0中還增加了x,y,translationX和translationY這幾個(gè)屬性,便于我們對(duì)view的平移操作,x、y代表了當(dāng)前view左上角的xy坐標(biāo),而translationX和translationY代表了view相對(duì)它的父容器的偏移量,默認(rèn)值是0。MotionEvent表示用戶的觸摸事件,用戶的一次點(diǎn)擊、觸摸或者滑動(dòng)都會(huì)產(chǎn)生一系列的MotionEvent:MotionEvent.ACTION_DOWN表示用戶的手指剛接觸到屏幕MotionEvent.ACTION_MOVE表示用戶的手指正在移動(dòng)MotionEvent.ACTION_UP表示用戶的手指從屏幕上抬起所以一次用戶觸摸屏幕可能會(huì)產(chǎn)生這些事件:點(diǎn)擊屏幕然后松開(kāi),Down->Up點(diǎn)擊屏幕,然后滑動(dòng)一段距離,松開(kāi)屏幕,Down->Move->…->Move->Up了解了這些基本知識(shí)以后,我們就來(lái)學(xué)習(xí)一下具體怎么分發(fā)這些事件ViewGroup分發(fā)->攔截->處理首先說(shuō)一點(diǎn),雖然ViewGroup也是繼承View而來(lái),但是因?yàn)樵谑录r截上,ViewGroup分析起來(lái)更加方便理解,所以先說(shuō)ViewGroup,下面也會(huì)簡(jiǎn)單介紹一下View的事件處理。在事件分發(fā)的過(guò)程中,主要涉及到三個(gè)方法:dispatchTouchEvent(MotionEventevent);onInterceptTouchEvent(MotionEventevent);onTouchEvent();初看這三個(gè)方法就有蒙圈,如果這時(shí)候在蒙頭鉆進(jìn)源碼里,就更是糊涂,我在這里借用任玉剛大大的一段偽代碼解釋一下這三者之間的關(guān)系:public
boolean
dispatchTouchEvent(MotionEvent
event)
{
boolean
consume
=
false;
if
(onInterceptTouchEvent(event))
{
consume
=
onTouchEvent(event);
}
else
{
consume
=
child.dispatchTouchEvent(event);
}
return
consume;
}從這段偽代碼中,我們可以看出來(lái),在dispatchTouchEvent中,先調(diào)用ViewGroup自身的onInterceptTouchEvent方法,判斷自己是否要攔截,如果這時(shí)候自己攔截,那就調(diào)用自己的onTouchEvent方法,如果onTouchEvent方法返回了True,那么這次的事件就算消耗了,事件傳遞到此為止,如果返回了False,證明這次沒(méi)有消耗這次MotionEvent,那么這次的事件就會(huì)往上返回,由上一級(jí)繼續(xù)處理;如果當(dāng)前ViewGroup的onInterceptTouchEvent返回了False,那就會(huì)調(diào)用它的子view的dispatchTouchEvent方法,這樣這個(gè)事件就傳遞下去了,如果它的子View處理不了,那么還會(huì)回來(lái)調(diào)用ViewGroup的onTouchEvent方法,當(dāng)然這一點(diǎn)是沒(méi)有在這一段偽代碼里體現(xiàn)的,用一段通俗的例子解釋:領(lǐng)導(dǎo)收到一份任務(wù)(有可能是上級(jí)給的),自己看了一眼,然后決定好好休息,今天不工作,就把這個(gè)任務(wù)交給了手下的小王,小王的默認(rèn)屬性是只要來(lái)任務(wù)就接,而且就干,能干不能干一樣接,如果這是一個(gè)簡(jiǎn)單的任務(wù),那么小王就解決了,這個(gè)任務(wù)也就完成了,不幸的是,這次任務(wù)小王沒(méi)有解決掉,然后向領(lǐng)導(dǎo)反饋,領(lǐng)導(dǎo)沒(méi)辦法,手下沒(méi)人能解決,只好自己干了,就開(kāi)始解決問(wèn)題,然后解決掉,任務(wù)也完成了。這就是ViewGroup層的事件分發(fā),當(dāng)然不是這么簡(jiǎn)單,這只不過(guò)是通過(guò)簡(jiǎn)單的方式去理解,其實(shí)在真實(shí)的事件分發(fā)中,有很多問(wèn)題需要注意:一個(gè)完成的事件序列以Down開(kāi)始,中間可能包含若干個(gè)Move,然后以Up結(jié)束一個(gè)view一旦攔截一個(gè)某個(gè)事件,當(dāng)前事件所在的完整事件序列將都會(huì)由這個(gè)view去處理,反應(yīng)在真實(shí)的代碼中,就是一旦view攔截了down事件,那么此后的move和up事件都將不調(diào)用onInterceptTouchEvent,而直接由它處理,這就也意味著在onInterceptTouchEvent處理事件是不合適的,因?yàn)橛锌赡軄?lái)了事件,卻直接跳過(guò)onInterceptTouchEvent方法。這個(gè)也意味著,一旦一個(gè)ViewGroup沒(méi)有攔截ACTION_DOWN,那么這個(gè)事件序列的其他Action,它都將收不到,所以在處理ACTION_DOWN的時(shí)候,尤其需要謹(jǐn)慎。onTouchEvent中是要判斷MotionEvent的Action,因?yàn)橐淮吸c(diǎn)擊操作就會(huì)調(diào)用兩次onTouchEvent方法,一次是ACTION_DOWN,一次是ACTION_UP,如果手滑一下,還會(huì)有若干個(gè)ACTION_MOVEViewGroup默認(rèn)不攔截任何事件,源碼中ViewGroup的onInterceptTouchEvent方法默認(rèn)返回的是false整個(gè)事件分發(fā),看起來(lái)都是由外向內(nèi)傳遞的,父View將事件傳遞給子View,理論上來(lái)看,子View是沒(méi)有辦法影響到父View的事件處理的,但是有一個(gè)標(biāo)示位,requestDisallowInterceptTouchEvent方法,通過(guò)這個(gè)方法
,子View能夠影響父view的事件處理,這個(gè)可以用于解決父view和子view的滑動(dòng)沖突,具體想了解的可以搜索它的相關(guān)用法,這里將不進(jìn)行展開(kāi)。View只有默默的承受View不同于ViewGroup的是,View中沒(méi)有onInterceptTouchEvent方法,因?yàn)閂iew作為事件處理的***一級(jí),不需要判斷是否要攔截,是一定要攔截,不管能不能處理,都要試一下,所以在View中調(diào)用流程是:dispatchTouchEvent->onTouchEvent而且,***onTouchEvent的返回值默認(rèn)都是True,也就是說(shuō)事件傳遞下去一般都會(huì)被消耗掉的,只是看中途是否有人攔截,這個(gè)時(shí)候讀者可能會(huì)有疑問(wèn):TextView的onTouchEvent的返回值也是True嗎?答案就是:是的,那為什么點(diǎn)在TextView上面還是能觸發(fā)它的父視圖的onTouchEvent,理論上不應(yīng)該是,TextView消耗掉這次的事件,不回傳。理論上確實(shí)是這樣,但是因?yàn)門extView的clickable和longClickable屬性都是false,當(dāng)這兩個(gè)屬性都為false的時(shí)候,是不會(huì)消耗事件的,所以TextView不會(huì)消耗事件,這也就可以解釋為什么把一個(gè)TextView放在一個(gè)Button上面,然后點(diǎn)擊TextView還是能觸發(fā)Button的點(diǎn)擊事件在這里可能需要提醒一下大家,算是一個(gè)我之前踩到的一個(gè)坑,我把一個(gè)view的enable狀態(tài)設(shè)成了false,然后又給它增加了onClickListener,這時(shí)候我本以為,它的點(diǎn)擊事件不會(huì)被觸發(fā),結(jié)果它還是可以被點(diǎn)擊,后來(lái)才了解到,view的enable狀態(tài)和onTouchEvent是沒(méi)有關(guān)系的,只有clickable狀態(tài)是對(duì)onTouchEvent有影響的,還有一點(diǎn)
,設(shè)置
view的enable為false確實(shí)也會(huì)把view的clickable設(shè)成false,但是設(shè)置view的onclickListener就又把view的clickable變成了true,所以***的解決方案就是把那兩行代碼換下先后順序,問(wèn)題就迎刃而解了。詳解處理GesutureDetector費(fèi)勁千辛萬(wàn)苦,終于把事件攔截下來(lái)了,然后我們需要總得做點(diǎn)什么吧,不然都對(duì)不起自己浪費(fèi)這么多口舌,說(shuō)到對(duì)事件的處理,我們首先想到的就是setOnClickListener,殊不知onClickListener的優(yōu)先級(jí)是***的,下一節(jié)里面會(huì)對(duì)優(yōu)先級(jí)進(jìn)行說(shuō)明,而這里,我們將主要想著如果處理事件,當(dāng)我們興奮地拿到一連串的事件,但又不知如何下手,甚至于連最簡(jiǎn)單的點(diǎn)擊事件都要自己進(jìn)行一番處理,更別提做成平移、旋轉(zhuǎn)、縮放這樣的操作,但是官方提供的GestureDetector給我們提供了可能。官方提供的GestureDetector是一個(gè)手勢(shì)輔助檢測(cè)類,默認(rèn)能夠檢測(cè)多種手勢(shì):class
SimpleGestureListener
implements
GestureDetector.OnGestureListener
{
@Override
public
boolean
onDown(MotionEvent
e)
{
return
false;
}
@Override
public
void
onShowPress(MotionEvent
e)
{
}
@Override
public
boolean
onSingleTapUp(MotionEvent
e)
{
return
false;
}
@Override
public
boolean
onScroll(MotionEvent
e1,
MotionEvent
e2,
float
distanceX,
float
distanceY)
{
return
false;
}
@Override
public
void
onLongPress(MotionEvent
e)
{
}
@Override
public
boolean
onFling(MotionEvent
e1,
MotionEvent
e2,
float
velocityX,
float
velocityY)
{
return
false;
}
}通過(guò)這個(gè)類,我們可以很方便的處理除了單擊和長(zhǎng)按之外,還有滑動(dòng),雙擊等各種手勢(shì),并對(duì)其分別進(jìn)行處理,如果這些還是不能滿足你的好奇心,那還有一個(gè)官方提供的ScaleGestureDetector,從名字就可以判斷出來(lái)這是一個(gè)檢測(cè)縮放手勢(shì)的輔助類,而且還有大牛仿照ScaleGestureDetector思路做出了平移以及旋轉(zhuǎn)的輔助類,然后我們就可以根據(jù)這些輔助類,幾乎為所欲為了,下面我寫了一個(gè)支持平移,縮放,旋轉(zhuǎn)的小Demo。private
void
init()
{
scaleGesture
=
new
ScaleGestureDetector(getContext(),
new
ScaleListener());
moveGesture
=
new
MoveGestureDetector(getContext(),
new
MovingListener());
rotateGesture
=
new
RotateGestureDetector(getContext(),
new
RotateListener());
}
@Override
public
boolean
onTouchEvent(MotionEvent
event)
{
scaleGesture.onTouchEvent(event);
moveGesture.onTouchEvent(event);
rotateGesture.onTouchEvent(event);
return
true;
}
private
class
ScaleListener
implements
ScaleGestureDetector.OnScaleGestureListener
{
@Override
public
boolean
onScale(ScaleGestureDetector
detector)
{
setScaleX(detector.getScaleFactor()
*
getScaleX());
setScaleY(detector.getScaleFactor()
*
getScaleY());
return
true;
}
@Override
public
bool
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 工程測(cè)量技術(shù)實(shí)踐訓(xùn)練題
- 2025年上半年宜昌市直事業(yè)單位招考工作人員(62名)易考易錯(cuò)模擬試題(共500題)試卷后附參考答案
- 2025年上半年宜賓江安縣招考工作人員易考易錯(cuò)模擬試題(共500題)試卷后附參考答案
- 2025年上半年安徽省阜陽(yáng)潁上縣江店孜鎮(zhèn)人民政府招聘易考易錯(cuò)模擬試題(共500題)試卷后附參考答案
- 2024年抽紗刺繡工藝品項(xiàng)目投資申請(qǐng)報(bào)告代可行性研究報(bào)告
- 2025年上半年安徽省宿州市直事業(yè)單位易考易錯(cuò)模擬試題(共500題)試卷后附參考答案
- 2025年上半年安徽省交通控股集團(tuán)限公司社會(huì)化公開(kāi)招聘易考易錯(cuò)模擬試題(共500題)試卷后附參考答案
- 2025年上半年安徽宿州市督查信息中心選調(diào)事業(yè)單位3人易考易錯(cuò)模擬試題(共500題)試卷后附參考答案
- 2025年上半年安徽宿州學(xué)院專職輔導(dǎo)員招聘10人(第二批)易考易錯(cuò)模擬試題(共500題)試卷后附參考答案
- 2025年上半年安慶市太湖縣縣人民醫(yī)院招考專業(yè)技術(shù)人員易考易錯(cuò)模擬試題(共500題)試卷后附參考答案
- 2025年食品供應(yīng)商合同范本
- 《網(wǎng)絡(luò)信息安全教學(xué)》課件
- 徐州2025年江蘇徐州市口腔醫(yī)院招聘非在編醫(yī)務(wù)人員53人筆試歷年參考題庫(kù)附帶答案詳解-1
- 2025年01月2025中國(guó)作家協(xié)會(huì)所屬單位公開(kāi)招聘11人筆試歷年典型考題(歷年真題考點(diǎn))解題思路附帶答案詳解
- 用色彩情感引發(fā)共鳴社交媒體運(yùn)營(yíng)秘訣
- 2025年江西機(jī)電職業(yè)技術(shù)學(xué)院高職單招職業(yè)技能測(cè)試近5年??及鎱⒖碱}庫(kù)含答案解析
- 2025年江蘇旅游職業(yè)學(xué)院高職單招職業(yè)技能測(cè)試近5年??及鎱⒖碱}庫(kù)含答案解析
- (高清版)JTGT 3650-01-2022 公路橋梁施工監(jiān)控技術(shù)規(guī)程
- GB/T 28799.2-2020冷熱水用耐熱聚乙烯(PE-RT)管道系統(tǒng)第2部分:管材
- 2023-瑞幸咖啡vi手冊(cè)
- 10000中國(guó)普通人名大全
評(píng)論
0/150
提交評(píng)論