這篇文章主要講解了“Android中如何實(shí)現(xiàn)View事件分發(fā)”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“Android中如何實(shí)現(xiàn)View事件分發(fā)”吧!

創(chuàng)新互聯(lián)是一家集網(wǎng)站建設(shè),漢川企業(yè)網(wǎng)站建設(shè),漢川品牌網(wǎng)站建設(shè),網(wǎng)站定制,漢川網(wǎng)站建設(shè)報(bào)價(jià),網(wǎng)絡(luò)營(yíng)銷,網(wǎng)絡(luò)優(yōu)化,漢川網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競(jìng)爭(zhēng)力。可充分滿足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時(shí)我們時(shí)刻保持專業(yè)、時(shí)尚、前沿,時(shí)刻以成就客戶成長(zhǎng)自我,堅(jiān)持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。
(1)ViewGroup.dispatchTouchEvent(event)
boolean dispatchTouchEvent(MotionEvent event) {
int action = event.getAction();
//判斷ViewGroup是否攔截touch事件。當(dāng)為ACTION_DOWN或者找到能夠接收touch事件的子View
時(shí),由onInterceptTouchEvent(event)決定是否攔截。其他情況,即ACTION_MOVE/ACTION_UP且
沒(méi)找到能夠接收touch事件的子View時(shí),直接攔截。
boolean intercepted;
if (action == MotionEvent.ACTION_DOWN || mFirstTouchTarget != null) {
intercepted = onInterceptTouchEvent(event);
} else {
intercepted = true;
}
//如果ViewGroup不攔截touch事件。在ACTION_DOWN時(shí)遍歷所有子View,查找能夠接收touch事件的
子View。如果找到則設(shè)置mFirstTouchTarget,并跳出循環(huán)。
boolean alreadyDispatchedToNewTouchTarget = false;
if (!intercepted) {
if (action == MotionEvent.ACTION_DOWN) {
for (int i = childrenCount - 1; i >= 0; i--) {
if (!canViewReceivePointerEvents(child) ||
!isTransformedTouchPointInView(x, y, child, null)) {
continue;
}
if (dispatchTransformedTouchEvent(event, child)) {
//找到mFirstTouchTarget
newTouchTarget = addTouchTarget(child);
alreadyDispatchedToNewTouchTarget = true;
break;
}
}
}
}
//事件下發(fā)及消費(fèi)。如果沒(méi)找到能夠接收touch事件的子View,則由ViewGroup自己處理及消費(fèi)。
如果找到能夠接收touch事件的子View,則由子View遞歸處理touch事件及消費(fèi)。
boolean handled = false;
if (mFirstTouchTarget == null) {
handled = dispatchTransformedTouchEvent(event, null);
} else {
if (alreadyDispatchedToNewTouchTarget) {
handled = true;
} else {
while (touchTarget) {
handled = dispatchTransformedTouchEvent(event, child);
}
}
}
return handled;
}
//ViewGroup事件下發(fā)。如果無(wú)接收touch事件的子View,則由ViewGroup的父類(即View)下發(fā)touch事件
如果child非空,則交由子View下發(fā)touch事件,子View可以是ViewGroup或View。
boolean dispatchTransformedTouchEvent(MotionEvent event, View child) {
boolean handled;
if (child == null) {
handled = super.dispatchTouchEvent(event);
} else {
handled = child.dispatchTouchEvent(event);
}
return handled;
}(2)View.dispatchTouchEvent(event)
//View的Touch事件分發(fā)。當(dāng)外部設(shè)置了mOnTouchListener時(shí),先交由mOnTouchListener.onTouch(event)消費(fèi)。
若未消費(fèi),則交給View的onTouchEvent(event)消費(fèi)。onTouchEvent的實(shí)現(xiàn)是,如果設(shè)置了mOnClickListener,
則執(zhí)行mOnClickListener.onClick()點(diǎn)擊事件。返回值為true,表示消費(fèi),否則未消費(fèi)。
boolean dispatchTouchEvent(MotionEvent event) {
boolean result = false;
if (mOnTouchListener != null && mOnTouchListener.onTouch(this, event)) {
result = true;
}
if (!result && onTouchEvent(event)) {
result = true;
}
return result;
}
boolean onTouchEvent(MotionEvent event) {
performClick();
}3.總結(jié)
總結(jié)下ViewGroup的事件分發(fā)及消費(fèi)過(guò)程:
整個(gè)過(guò)程包括3個(gè)部分:判斷是否攔截 -> 查找接收touch事件的子View -> 事件下發(fā)及消費(fèi)
判斷是否攔截:
(1) ACTION_DOWN 或者 非ACTION_DOWN且找到接收touch事件的子View時(shí),由onInterceptTouchEvent(event)決定是否攔截
(2) 非ACTION_DOWN,且未找到接收touch事件的子View時(shí),標(biāo)明需要攔截touch事件
這里解釋下,影響ViewGroup是否能攔截touch事件有2個(gè)因素:是否 找到了接收touch事件的子View 和 onInterceptTouchEvent(event). 而查找接收touch事件的子View這一過(guò)程只需要在ACTION_DOWN的時(shí)候確定好就行。如果ACTION_DOWN的時(shí)候沒(méi)找到,那么ACTION_MOVE和ACTION_UP肯定也找不到,因此touch事件直接被ViewGroup攔截。如果找到了接收touch事件的子View,那么ACTION_MOVE和ACTION_UP情況下還是要檢查下ViewGroup的onInterceptTouchEvent(event),看下是否攔截。
查找接收touch事件的子View:
(1) 兩種情況下查找:ACTION_DOWN且ViewGroup不攔截的情況下。
(2) 查找方法:遍歷所有子View,如果touch事件的xy坐標(biāo)在該ViewGroup的某個(gè)子View范圍內(nèi),則針對(duì)該子View執(zhí)行遞歸分發(fā)touch事件操作,如果找到有子View處理touch事件(return true),則跳出循環(huán)。
這里解釋下查找條件。查找接收touch事件的子View,顯然只需要ACTION_DOWN情況下即可,沒(méi)必要ACTION_MOVE和ACTION_UP都檢查,否則重復(fù)操作。如果ViewGroup都已經(jīng)攔截了,顯然不需要再去考慮子View怎么樣了。
事件下發(fā)及消費(fèi):
(1)兩種情況:ViewGroup下發(fā)及消費(fèi) 或者 ViewGroup的子View下發(fā)及消費(fèi)
(2)如果經(jīng)過(guò)以上兩步,沒(méi)找到接收Touch事件的子View,那么由ViewGroup進(jìn)行下發(fā)及消費(fèi),下發(fā)及調(diào)用流程是:ViewGroup.dispatchTouchEvent -> View.dispatchTouchEvent -> mOnTouchListener.onTouch -> onTouchEvent -> onClick
(3)如果找到接收touch事件的子View,則針對(duì)該子View執(zhí)行touch事件遞歸下發(fā)及消費(fèi)的操作
補(bǔ)充:
(1) 源碼中,mFirstTouchEvent表示接收touch事件的子View
(2) 步驟2和3,都有執(zhí)行dispatchTransformedTouchEvent(event, child)的操作,步驟2中只是為了查找接收touch事件的子View,步驟3主要目的是進(jìn)行事件分發(fā)及消費(fèi)。如果步驟2中針對(duì)某個(gè)子View已經(jīng)執(zhí)行了該方法,則步驟3中不再重復(fù)執(zhí)行。個(gè)人理解,不知道是否有誤。
4.結(jié)論
(1) 回調(diào)方法
ViewGroup:dispatchTouchEvent -> onInterceptTouchEvent -> onTouchEvent
View: dispatchTouchEvent -> onTouch
(2) 調(diào)用順序
Action執(zhí)行順序:ACTION_DOWN -> ACTION_MOVE -> ACTION_UP
ViewGroup: dispatchTouchEvent -> onInterceptTouchEvent -> onTouchEvent()
View: dispatchTouchEvent -> onTouchEvent
事件分發(fā)傳遞順序: Parent View -> Child View
ViewGroup1.dispatchTouchEvent -> ViewGroup2.dispatchTouchEvent
-> View3.dispatchTouchEvent
(緊跟著是View3.onTouchEvent)
事件消費(fèi)傳遞順序:Child View -> Parent View
View3.onTouchEvent -> ViewGroup2.onTouchEvent
-> ViewGroup1.onTouchEvent
感謝各位的閱讀,以上就是“Android中如何實(shí)現(xiàn)View事件分發(fā)”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)Android中如何實(shí)現(xiàn)View事件分發(fā)這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!
當(dāng)前題目:Android中如何實(shí)現(xiàn)View事件分發(fā)
標(biāo)題URL:http://chinadenli.net/article22/jiiscc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供Google、網(wǎng)站導(dǎo)航、品牌網(wǎng)站設(shè)計(jì)、、網(wǎng)站設(shè)計(jì)、App開(kāi)發(fā)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)