日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
Android事件分發(fā)機(jī)制

事件分發(fā)機(jī)制

Android事件分發(fā)是指在Android系統(tǒng)中,當(dāng)用戶觸摸屏幕或執(zhí)行其他操作時(shí),系統(tǒng)如何將這些事件傳遞給正確的視圖或組件進(jìn)行處理的過(guò)程。

創(chuàng)新互聯(lián)-專(zhuān)業(yè)網(wǎng)站定制、快速模板網(wǎng)站建設(shè)、高性價(jià)比新洲網(wǎng)站開(kāi)發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫(kù),直接使用。一站式新洲網(wǎng)站制作公司更省心,省錢(qián),快速模板網(wǎng)站建設(shè)找我們,業(yè)務(wù)覆蓋新洲地區(qū)。費(fèi)用合理售后完善,十年實(shí)體公司更值得信賴。

Android事件分發(fā)遵循一種稱為"事件分發(fā)機(jī)制"的規(guī)則,該機(jī)制由三個(gè)主要的階段組成:觸摸事件的捕獲階段、目標(biāo)視圖的處理階段和冒泡階段。

在觸摸事件的捕獲階段,事件從頂層視圖(如Activity)開(kāi)始,逐級(jí)向下傳遞,直到找到最底層的子視圖。在這個(gè)過(guò)程中,每個(gè)視圖都有機(jī)會(huì)攔截事件,如果某個(gè)視圖攔截了事件,則后續(xù)的視圖將無(wú)法接收到該事件。

在目標(biāo)視圖的處理階段,事件被傳遞給最底層的子視圖,并由該視圖進(jìn)行處理。如果該視圖沒(méi)有處理事件,則事件將被傳遞給其父視圖,直到找到能夠處理事件的視圖為止。

在冒泡階段,事件從底層視圖向上冒泡,直到達(dá)到頂層視圖。在這個(gè)過(guò)程中,每個(gè)視圖都有機(jī)會(huì)處理事件,如果某個(gè)視圖處理了事件,則后續(xù)的視圖將無(wú)法接收到該事件。

通過(guò)這種事件分發(fā)機(jī)制,Android系統(tǒng)能夠準(zhǔn)確地將用戶的操作傳遞給正確的視圖或組件進(jìn)行處理,從而實(shí)現(xiàn)了用戶與應(yīng)用程序的交互。在實(shí)際開(kāi)發(fā)中,我們可以通過(guò)重寫(xiě)視圖的相關(guān)方法(如onTouchEvent())來(lái)自定義事件的處理邏輯,以滿足特定的需求。

涉及的對(duì)象

  1. View:View是Android中的基本UI組件,它負(fù)責(zé)接收用戶的輸入事件(如點(diǎn)擊、觸摸等),并將事件傳遞給相應(yīng)的處理方法。
  2. ViewGroup:ViewGroup是View的子類(lèi),它可以包含其他的View或ViewGroup。當(dāng)一個(gè)事件發(fā)生在ViewGroup上時(shí),它會(huì)遍歷其子View,并將事件傳遞給合適的子View。
  3. MotionEvent:MotionEvent是Android中的事件對(duì)象,它封裝了用戶的觸摸事件信息,包括觸摸點(diǎn)的坐標(biāo)、觸摸的動(dòng)作等。
  4. MotionEventCompat:MotionEventCompat是一個(gè)兼容性類(lèi),用于處理不同Android版本之間的觸摸事件兼容性問(wèn)題。
  5. GestureDetector:GestureDetector是Android提供的手勢(shì)檢測(cè)器,它可以識(shí)別用戶的手勢(shì)操作,如滑動(dòng)、長(zhǎng)按、雙擊等。
  6. OnTouchListener:OnTouchListener是一個(gè)接口,用于監(jiān)聽(tīng)View的觸摸事件。通過(guò)實(shí)現(xiàn)該接口,可以自定義觸摸事件的處理邏輯。

以上是事件分發(fā)中的一些關(guān)鍵對(duì)象,它們共同協(xié)作,實(shí)現(xiàn)了Android中的事件分發(fā)機(jī)制。

MotionEvent

MotionEvent是Android中的一個(gè)類(lèi),用于處理與用戶交互相關(guān)的事件,例如觸摸屏幕、按下按鈕等。它包含了一系列的常量和方法,用于獲取事件的類(lèi)型、坐標(biāo)、時(shí)間等信息。通過(guò)監(jiān)聽(tīng)MotionEvent,開(kāi)發(fā)者可以實(shí)現(xiàn)對(duì)用戶的觸摸操作進(jìn)行響應(yīng)和處理。

以下是一些常用的MotionEvent方法:

  • getAction():獲取觸摸事件的動(dòng)作類(lèi)型,返回一個(gè)整數(shù)值??梢酝ㄟ^(guò)使用MotionEvent.ACTION_DOWN、MotionEvent.ACTION_MOVE、MotionEvent.ACTION_UP等常量來(lái)判斷觸摸事件的具體類(lèi)型。
  • getDownTime():獲取當(dāng)屏幕剛被按下時(shí)的時(shí)間(毫秒),按下后移動(dòng)此時(shí)間不變
  • getEventTime():獲取MotionEvent所在的事件被激發(fā)的時(shí)間(毫秒)
  • getX()和getY():獲取觸摸事件的發(fā)生位置的橫坐標(biāo)和縱坐標(biāo)。返回的是相對(duì)于觸摸事件發(fā)生位置的坐標(biāo)值。
  • getRawX()和getRawY():獲取觸摸事件的發(fā)生位置的原始橫坐標(biāo)和縱坐標(biāo)。返回的是相對(duì)于屏幕的坐標(biāo)值。
  • getPointerCount():獲取觸摸事件中手指的數(shù)量。
  • getPointerId(int pointerIndex):獲取指定索引的手指的ID。
  • getPressure(int pointerIndex):獲取指定索引的手指的壓力值。
  • getHistorySize():獲取觸摸事件的歷史記錄的數(shù)量。
  • getHistoricalX(int pointerIndex, int pos)和getHistoricalY(int pointerIndex, int pos):獲取指定索引的手指在指定歷史記錄位置的橫坐標(biāo)和縱坐標(biāo)。

這些方法可以幫助開(kāi)發(fā)者獲取觸摸事件的相關(guān)信息,并進(jìn)行相應(yīng)的處理。

MotionEvent#getAction()類(lèi)型

MotionEvent#getAction()方法返回一個(gè)整數(shù),表示當(dāng)前觸摸事件的類(lèi)型。具體的類(lèi)型有以下幾種:

  • ACTION_DOWN:手指按下屏幕時(shí)觸發(fā)的事件
  • ACTION_MOVE:手指在屏幕上滑動(dòng)時(shí)觸發(fā)的事件
  • ACTION_UP:手指離開(kāi)屏幕時(shí)觸發(fā)的事件
  • ACTION_CANCEL:觸摸事件被取消時(shí)觸發(fā)的事件
  • ACTION_OUTSIDE:超出區(qū)域

這些類(lèi)型可以通過(guò)與MotionEvent類(lèi)中定義的常量進(jìn)行比較來(lái)判斷當(dāng)前觸摸事件的類(lèi)型。例如,可以使用以下代碼來(lái)判斷當(dāng)前事件是否為按下事件:

if (event.getAction() == MotionEvent.ACTION_DOWN) {
    // 處理按下事件的邏輯
}

示例:手指觸摸屏幕到離開(kāi)屏幕事件走向

圖片

事件分發(fā)對(duì)象間傳遞

在Android中,事件分發(fā)是通過(guò)View的事件分發(fā)機(jī)制來(lái)實(shí)現(xiàn)的。當(dāng)用戶觸摸屏幕或者進(jìn)行其他操作時(shí),事件會(huì)從頂層的ViewGroup開(kāi)始向下傳遞,直到找到合適的View來(lái)處理該事件。

Android中的事件分發(fā)涉及到以下幾個(gè)對(duì)象:

  1. Activity:Activity是Android應(yīng)用程序的一個(gè)組件,它負(fù)責(zé)管理用戶界面和處理用戶交互。當(dāng)用戶觸摸屏幕或者進(jìn)行其他操作時(shí),事件首先會(huì)傳遞給當(dāng)前顯示的Activity。
  2. Window:Window是Activity的一個(gè)屬性,它表示一個(gè)窗口,用于顯示Activity的用戶界面。事件會(huì)首先傳遞給Window,然后由Window負(fù)責(zé)將事件傳遞給對(duì)應(yīng)的View。
  3. View:View是Android中的基本UI組件,用于構(gòu)建用戶界面。每個(gè)View都有一個(gè)事件分發(fā)的責(zé)任,它可以處理自己感興趣的事件,也可以將事件傳遞給其他View。
  4. ViewGroup:ViewGroup是View的子類(lèi),用于管理其他View的布局和顯示。當(dāng)事件傳遞到ViewGroup時(shí),它會(huì)遍歷自己的子View,并將事件傳遞給合適的子View。

在事件分發(fā)過(guò)程中,每個(gè)對(duì)象都有機(jī)會(huì)處理事件。如果一個(gè)對(duì)象處理了事件,那么事件就會(huì)停止傳遞。如果一個(gè)對(duì)象沒(méi)有處理事件,那么事件會(huì)繼續(xù)向下傳遞,直到找到合適的處理者或者事件傳遞到最底層的View。

可以通過(guò)重寫(xiě)View的dispatchTouchEvent()方法來(lái)實(shí)現(xiàn)事件的分發(fā)和傳遞。在該方法中,可以根據(jù)需要調(diào)用super.dispatchTouchEvent()方法將事件傳遞給父View或者調(diào)用View的onTouchEvent()方法來(lái)處理事件。

Android中的事件分發(fā)是通過(guò)Activity、Window、View和ViewGroup等對(duì)象之間的協(xié)作來(lái)實(shí)現(xiàn)的。每個(gè)對(duì)象都有機(jī)會(huì)處理事件,通過(guò)合理地重寫(xiě)相關(guān)方法,可以實(shí)現(xiàn)事件的傳遞和處理。

事件分發(fā)機(jī)制解析

從上面的文章中我們得知Android事件分發(fā)機(jī)制的傳遞過(guò)程可以分為三個(gè)階段:分發(fā)、攔截和處理。

  1. 分發(fā)階段:事件首先由Activity或ViewGroup的dispatchTouchEvent()方法開(kāi)始分發(fā)。在這個(gè)方法中,事件會(huì)被傳遞給當(dāng)前ViewGroup的onInterceptTouchEvent()方法進(jìn)行攔截判斷。如果onInterceptTouchEvent()返回true,則表示當(dāng)前ViewGroup攔截了事件,不再向下傳遞;如果返回false,則表示當(dāng)前ViewGroup不攔截事件,會(huì)繼續(xù)向下傳遞。
  2. 攔截階段:如果當(dāng)前ViewGroup不攔截事件,事件會(huì)繼續(xù)向下傳遞給子View。子View的dispatchTouchEvent()方法會(huì)被調(diào)用,同樣會(huì)經(jīng)過(guò)onInterceptTouchEvent()方法的判斷。如果子View攔截了事件,那么事件將不再向下傳遞給其他子View,而是交給子View的onTouchEvent()方法進(jìn)行處理;如果子View不攔截事件,事件會(huì)繼續(xù)向下傳遞。
  3. 處理階段:如果事件沒(méi)有被任何ViewGroup或View攔截,最終會(huì)傳遞給最底層的View的onTouchEvent()方法進(jìn)行處理。在這個(gè)方法中,可以根據(jù)事件的類(lèi)型(如觸摸、滑動(dòng)、點(diǎn)擊等)進(jìn)行相應(yīng)的處理操作。

Android事件分發(fā)機(jī)制的傳遞過(guò)程是從上到下的遞歸過(guò)程,事件會(huì)依次經(jīng)過(guò)父ViewGroup和子View的攔截判斷,最終到達(dá)最底層的View進(jìn)行處理。這個(gè)過(guò)程中,可以通過(guò)重寫(xiě)相關(guān)方法來(lái)實(shí)現(xiàn)事件的攔截和處理,從而實(shí)現(xiàn)自定義的交互邏輯。

Activity事件分發(fā)機(jī)制

Activity的事件分發(fā)機(jī)制是通過(guò)ViewGroup和View的層級(jí)關(guān)系來(lái)實(shí)現(xiàn)的。當(dāng)用戶觸摸屏幕或者按下按鍵時(shí),系統(tǒng)會(huì)將事件傳遞給當(dāng)前顯示的Activity的根布局ViewGroup,然后由ViewGroup負(fù)責(zé)將事件分發(fā)給各個(gè)子View進(jìn)行處理。

具體的事件分發(fā)流程如下:

  1. 用戶觸摸屏幕或按下按鍵,事件首先傳遞給Activity的根布局ViewGroup。
  2. ViewGroup會(huì)調(diào)用自己的dispatchTouchEvent()方法來(lái)處理事件。在該方法中,ViewGroup會(huì)根據(jù)事件的類(lèi)型(如觸摸事件、按鍵事件等)進(jìn)行相應(yīng)的處理,例如判斷是否需要攔截事件、是否需要消費(fèi)事件等。
  3. 如果ViewGroup需要攔截事件,即認(rèn)為自己應(yīng)該處理該事件,那么事件就會(huì)停止向下傳遞,直接由ViewGroup來(lái)處理。
  4. 如果ViewGroup不需要攔截事件,那么事件會(huì)繼續(xù)向下傳遞給子View。
  5. 子View會(huì)依次接收事件,并調(diào)用自己的dispatchTouchEvent()方法來(lái)處理事件。子View也會(huì)根據(jù)事件的類(lèi)型進(jìn)行相應(yīng)的處理,例如判斷是否需要攔截事件、是否需要消費(fèi)事件等。
  6. 如果子View需要攔截事件,那么事件就會(huì)停止向下傳遞,直接由該子View來(lái)處理。
  7. 如果子View不需要攔截事件,那么事件會(huì)繼續(xù)向下傳遞給下一個(gè)子View,直到事件被消費(fèi)或者傳遞到最后一個(gè)子View。
  8. 如果事件最終沒(méi)有被任何子View消費(fèi),那么事件會(huì)回到ViewGroup,ViewGroup會(huì)根據(jù)自身的情況來(lái)決定是否消費(fèi)事件。
  9. 如果事件最終還是沒(méi)有被消費(fèi),那么事件會(huì)繼續(xù)向上層傳遞,直到被消費(fèi)或者傳遞到最頂層的Activity。

通過(guò)這樣的事件分發(fā)機(jī)制,Android系統(tǒng)可以實(shí)現(xiàn)對(duì)用戶的觸摸和按鍵事件進(jìn)行靈活的處理,從而實(shí)現(xiàn)各種交互效果。

Activity源碼:

public boolean dispatchTouchEvent(MotionEvent ev) {
    // 開(kāi)始事件都是Dwon,一般第一次都會(huì)進(jìn)入到onUserInteraction
    if (ev.getAction() == MotionEvent.ACTION_DOWN) {
        onUserInteraction();
    }
    // 若Window返回true,則會(huì)告訴Activity也返回true。true在所有touch代表著終止,不再繼續(xù)往下一個(gè)事件傳遞了
    if (getWindow().superDispatchTouchEvent(ev)) {
        return true;
    }
    return onTouchEvent(ev);
}

下面看getWindow().superDispatchTouchEvent(ev); Window是個(gè)抽象類(lèi),唯一實(shí)現(xiàn)類(lèi)為PhoneWindow,定位到PhoneWindow的superDispatchTouchEvent()。

PhoneWindow的源碼:

@Override
public boolean superDispatchTouchEvent(MotionEvent event) {
    return mDecor.superDispatchTouchEvent(event);
}

mDecor是DecorView類(lèi),DecorView是PhoneWindow類(lèi)的一個(gè)內(nèi)部類(lèi)。同時(shí)DecorView也是整個(gè)Window中的最頂層View。

DecorView

DecorView是Android中的一個(gè)類(lèi),它是Android系統(tǒng)中的頂級(jí)視圖,用于承載應(yīng)用程序的用戶界面。它是Android窗口系統(tǒng)的一部分,負(fù)責(zé)管理應(yīng)用程序的窗口和布局。

DecorView是一個(gè)特殊的ViewGroup,它包含了應(yīng)用程序的整個(gè)用戶界面,包括狀態(tài)欄、標(biāo)題欄、內(nèi)容區(qū)域等。它是Android應(yīng)用程序的根視圖,所有其他視圖都是DecorView的子視圖。

DecorView的主要作用是提供一個(gè)容器,用于放置應(yīng)用程序的布局和控件。它還負(fù)責(zé)處理用戶輸入事件,如觸摸、滑動(dòng)等,并將其傳遞給相應(yīng)的子視圖進(jìn)行處理。

在Android開(kāi)發(fā)中,我們通常不直接操作DecorView,而是通過(guò)Activity或Fragment來(lái)管理和操作應(yīng)用程序的用戶界面。DecorView在內(nèi)部被Activity或Fragment自動(dòng)創(chuàng)建和管理,開(kāi)發(fā)者只需要關(guān)注布局和控件的設(shè)計(jì)和交互邏輯即可。

DecorView是Android應(yīng)用程序的根視圖,負(fù)責(zé)承載應(yīng)用程序的用戶界面,并提供容器和事件處理功能。

DecorView是一個(gè)特殊的ViewGroup,分發(fā)處理同ViewGroup,下面看ViewGroup的superDispatchTouchEvent()

public boolean superDispatchTouchEvent(MotionEvent event) {
    return super.dispatchTouchEvent(event);
}

整個(gè)Activity事件分發(fā)過(guò)程如下圖:

圖片

ViewGroup事件分發(fā)機(jī)制

ViewGroup是一種特殊的View,它可以包含其他的View或者ViewGroup。當(dāng)用戶進(jìn)行觸摸操作時(shí),事件會(huì)被傳遞給ViewGroup,并由ViewGroup負(fù)責(zé)將事件分發(fā)給其子View或者子ViewGroup。

ViewGroup的事件分發(fā)機(jī)制主要包括以下幾過(guò)程:

  1. 事件的傳遞:當(dāng)用戶觸摸屏幕時(shí),事件會(huì)首先傳遞給最頂層的ViewGroup,即Activity的根布局。然后,ViewGroup會(huì)根據(jù)觸摸事件的坐標(biāo)位置,確定哪個(gè)子View或者子ViewGroup應(yīng)該接收該事件。
  2. 事件的攔截:在確定了接收事件的子View或者子ViewGroup后,ViewGroup會(huì)調(diào)用該子View或者子ViewGroup的dispatchTouchEvent()方法,將事件傳遞給它們。在這個(gè)過(guò)程中,如果父ViewGroup需要攔截事件,可以通過(guò)重寫(xiě)onInterceptTouchEvent()方法來(lái)實(shí)現(xiàn)。如果父ViewGroup攔截了事件,那么該事件將不會(huì)傳遞給子View或者子ViewGroup,而是由父ViewGroup來(lái)處理。
  3. 事件的處理:當(dāng)事件傳遞到子View或者子ViewGroup時(shí),它們會(huì)調(diào)用自己的dispatchTouchEvent()方法來(lái)處理事件。在這個(gè)方法中,子View或者子ViewGroup可以根據(jù)自己的需求來(lái)處理事件,例如響應(yīng)點(diǎn)擊、滑動(dòng)等操作。如果子View或者子ViewGroup不消費(fèi)事件,那么事件會(huì)繼續(xù)傳遞給父ViewGroup,直到事件被消費(fèi)或者傳遞到最頂層的ViewGroup。

ViewGroup的事件分發(fā)機(jī)制是通過(guò)事件的傳遞、攔截和處理來(lái)實(shí)現(xiàn)的。通過(guò)重寫(xiě)dispatchTouchEvent()和onInterceptTouchEvent()方法,可以對(duì)事件進(jìn)行自定義的處理。這種機(jī)制可以保證事件在ViewGroup及其子View或者子ViewGroup之間的正確傳遞和處理。

整個(gè)ViewGroup分發(fā)過(guò)程如下圖:

圖片

View事件分發(fā)機(jī)制

View事件分發(fā)機(jī)制主要包括三個(gè)關(guān)鍵方法:dispatchTouchEvent、onInterceptTouchEvent和onTouchEvent。

  1. dispatchTouchEvent:該方法是ViewGroup類(lèi)中的一個(gè)關(guān)鍵方法,用于分發(fā)觸摸事件。當(dāng)一個(gè)觸摸事件發(fā)生時(shí),系統(tǒng)會(huì)首先將該事件傳遞給頂層的ViewGroup,然后由ViewGroup根據(jù)一定的規(guī)則將事件傳遞給子View進(jìn)行處理。在dispatchTouchEvent方法中,系統(tǒng)會(huì)根據(jù)事件類(lèi)型和觸摸位置等信息,決定將事件傳遞給哪個(gè)子View進(jìn)行處理。
  2. onInterceptTouchEvent:該方法也是ViewGroup類(lèi)中的一個(gè)關(guān)鍵方法,用于攔截觸摸事件。當(dāng)一個(gè)觸摸事件傳遞給ViewGroup后,ViewGroup會(huì)先調(diào)用onInterceptTouchEvent方法來(lái)判斷是否需要攔截該事件。如果onInterceptTouchEvent方法返回true,則表示ViewGroup會(huì)攔截該事件,并將事件傳遞給自己的onTouchEvent方法進(jìn)行處理;如果返回false,則表示ViewGroup不會(huì)攔截該事件,會(huì)將事件繼續(xù)傳遞給子View進(jìn)行處理。
  3. onTouchEvent:該方法是View類(lèi)中的一個(gè)關(guān)鍵方法,用于處理觸摸事件。當(dāng)一個(gè)觸摸事件傳遞到View時(shí),View會(huì)調(diào)用自己的onTouchEvent方法來(lái)處理該事件。在onTouchEvent方法中,可以根據(jù)事件類(lèi)型進(jìn)行相應(yīng)的處理,例如處理點(diǎn)擊事件、滑動(dòng)事件等。

View事件分發(fā)機(jī)制的流程如下:

  1. 當(dāng)用戶觸摸屏幕時(shí),系統(tǒng)會(huì)將觸摸事件傳遞給頂層的ViewGroup。
  2. ViewGroup會(huì)調(diào)用dispatchTouchEvent方法來(lái)分發(fā)觸摸事件。
  3. 在dispatchTouchEvent方法中,ViewGroup會(huì)根據(jù)一定的規(guī)則將事件傳遞給子View進(jìn)行處理。
  4. 子View會(huì)先調(diào)用onInterceptTouchEvent方法來(lái)判斷是否需要攔截該事件。
  5. 如果onInterceptTouchEvent方法返回true,則表示ViewGroup會(huì)攔截該事件,并將事件傳遞給自己的onTouchEvent方法進(jìn)行處理。
  6. 如果onInterceptTouchEvent方法返回false,則表示ViewGroup不會(huì)攔截該事件,會(huì)將事件繼續(xù)傳遞給子View進(jìn)行處理。
  7. 子View會(huì)調(diào)用自己的onTouchEvent方法來(lái)處理觸摸事件。

View#dispatchTouchEvent源碼:

public boolean dispatchTouchEvent(MotionEvent event) {
    ...
    if (li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED && li.mOnTouchListener.onTouch(this, event)) {
        result = true;
    }
    ...
}

只有當(dāng)4個(gè)條件都為真才返回true,否則執(zhí)行onTouchEvent(),下面對(duì)這4個(gè)條件逐個(gè)分析:

  • li != null:li即是ListenerInfo,ListenerInfo是封裝了所有事件,所以只要賦值任一事件,這個(gè)都不可能會(huì)為null。
  • mOnTouchListener != null:mOnTouchListener變量在View.setOnTouchListener()方法里賦值,即只要我們給控件注冊(cè)了Touch事件,mOnTouchListener就不為空。
  • (mViewFlags & ENABLED_MASK) == ENABLED:判斷當(dāng)前點(diǎn)擊的控件是否enable,由于View默認(rèn)enable,故該條件為true。
  • mOnTouchListener.onTouch(this, event):控件注冊(cè)touch事件時(shí)重寫(xiě)的onTouch()方法。

若在setOnTouchListener返回true,就會(huì)滿足以上4個(gè)條件,并且返回了true,從而使得View.dispatchTouchEvent()直接返回true,事件分發(fā)結(jié)束,不會(huì)執(zhí)行onTouchEvent(event)。

View#onTouchEvent(event)源碼:

public boolean onTouchEvent(MotionEvent event) {
    ...
    // clickable代表該控件是否可點(diǎn)擊,可點(diǎn)擊就進(jìn)入下面條件判斷
    if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
        switch (action) {
            // 1. 當(dāng)前的事件 = 抬起View
            case MotionEvent.ACTION_UP:
                // 經(jīng)過(guò)種種判斷,此處省略
                ........
                if (!focusTaken) {
                    // 執(zhí)行performClick()
                    if (mPerformClick == null) {
                        mPerformClick = new PerformClick();
                    }
                    if (!post(mPerformClick)) {
                        performClickInternal();
                    }
                }
                break;
                // 2. 當(dāng)前的事件 = 按下View
                case MotionEvent.ACTION_DOWN:
                    // 經(jīng)過(guò)種種判斷,此處省略
                    break;
                // 3. 當(dāng)前的事件 = 結(jié)束事件(非人為原因)
                case MotionEvent.ACTION_CANCEL:
                    // 經(jīng)過(guò)種種判斷,此處省略
                    break;
                // 4. 當(dāng)前的事件 = 滑動(dòng)View
                case MotionEvent.ACTION_MOVE:
                    // 經(jīng)過(guò)種種判斷,此處省略
                    break;
            }
            // 若該控件可點(diǎn)擊,就一定返回true
            return true;
        }
    // 若該控件不可點(diǎn)擊,就一定返回false
    return false;
    ...
}

整個(gè)View分發(fā)過(guò)程如下圖:

圖片

總結(jié)

圖片

dispatchTouchEvent

dispatchTouchEvent用于分發(fā)觸摸事件。它是ViewGroup類(lèi)中的一個(gè)方法,用于將觸摸事件傳遞給子View或處理自身的觸摸事件。

觸摸事件的傳遞是通過(guò)觸摸事件分發(fā)機(jī)制來(lái)實(shí)現(xiàn)的。當(dāng)用戶觸摸屏幕時(shí),系統(tǒng)會(huì)將觸摸事件傳遞給頂層的ViewGroup,然后由ViewGroup負(fù)責(zé)將觸摸事件傳遞給子View或處理自身的觸摸事件。

dispatchTouchEvent方法的作用是將觸摸事件分發(fā)給子View或處理自身的觸摸事件。它會(huì)根據(jù)觸摸事件的類(lèi)型和位置來(lái)確定是將觸摸事件傳遞給子View,還是處理自身的觸摸事件。

在dispatchTouchEvent方法中,會(huì)依次調(diào)用onInterceptTouchEvent方法和onTouchEvent方法來(lái)判斷是否攔截觸摸事件和處理觸摸事件。如果onInterceptTouchEvent方法返回true,則表示攔截觸摸事件,不再向子View傳遞觸摸事件;如果onTouchEvent方法返回true,則表示處理了觸摸事件,不再向子View傳遞觸摸事件。

onTouchEvent

onTouchEvent用于處理觸摸事件。它是View類(lèi)的一個(gè)成員方法,可以被重寫(xiě)以實(shí)現(xiàn)自定義的觸摸事件處理邏輯。

觸摸事件包括按下(ACTION_DOWN)、移動(dòng)(ACTION_MOVE)、抬起(ACTION_UP)等多個(gè)動(dòng)作。當(dāng)用戶觸摸屏幕時(shí),系統(tǒng)會(huì)將觸摸事件傳遞給相應(yīng)的View,并調(diào)用該View的onTouchEvent方法來(lái)處理事件。

在onTouchEvent方法中,可以根據(jù)不同的觸摸動(dòng)作進(jìn)行相應(yīng)的處理,例如根據(jù)觸摸位置進(jìn)行繪制、處理滑動(dòng)事件、處理點(diǎn)擊事件等??梢酝ㄟ^(guò)重寫(xiě)onTouchEvent方法來(lái)實(shí)現(xiàn)自定義的觸摸交互效果。

重寫(xiě)onTouchEvent方法來(lái)處理觸摸事件:

@Override
public boolean onTouchEvent(MotionEvent event) {
    int action = event.getAction();
    switch (action) {
        case MotionEvent.ACTION_DOWN:
            // 處理按下事件
            break;
        case MotionEvent.ACTION_MOVE:
            // 處理移動(dòng)事件
            break;
        case MotionEvent.ACTION_UP:
            // 處理抬起事件
            break;
    }
    return true;
}

需要注意的是,onTouchEvent方法的返回值為boolean類(lèi)型。如果返回true,表示已經(jīng)處理了該觸摸事件,不再向其他View傳遞;如果返回false,則會(huì)將該觸摸事件傳遞給父View或其他相關(guān)的View進(jìn)行處理。

onInterceptTouchEvent

onInterceptTouchEvent用于攔截觸摸事件。它通常用于父容器對(duì)子View的觸摸事件進(jìn)行攔截和處理。

觸摸事件是由屏幕上的觸摸點(diǎn)產(chǎn)生的,包括按下、移動(dòng)和抬起等動(dòng)作。當(dāng)一個(gè)觸摸事件發(fā)生時(shí),系統(tǒng)會(huì)將該事件傳遞給最上層的View,并通過(guò)dispatchTouchEvent方法進(jìn)行分發(fā)。在分發(fā)過(guò)程中,如果父容器的onInterceptTouchEvent方法返回true,則表示父容器要攔截該事件,不再將事件傳遞給子View;如果返回false,則表示父容器不攔截該事件,繼續(xù)將事件傳遞給子View。

onInterceptTouchEvent方法的返回值決定了是否攔截觸摸事件,它有三種可能的返回值:

  • 返回true:表示父容器要攔截觸摸事件,不再傳遞給子View。
  • 返回false:表示父容器不攔截觸摸事件,繼續(xù)傳遞給子View。
  • 返回super.onInterceptTouchEvent(event):表示父容器不對(duì)觸摸事件進(jìn)行攔截,繼續(xù)按照默認(rèn)的方式處理。

通過(guò)在onInterceptTouchEvent方法中對(duì)觸摸事件進(jìn)行處理,我們可以實(shí)現(xiàn)一些特定的觸摸事件邏輯,例如滑動(dòng)沖突處理、多指觸摸事件的處理等。

setOnTouchListener

setOnTouchListener是一個(gè)用于設(shè)置觸摸事件監(jiān)聽(tīng)器的方法,用于對(duì)觸摸事件進(jìn)行處理。

使用setOnTouchListener方法,可以為一個(gè)控件(如Button、ImageView等)設(shè)置一個(gè)觸摸事件監(jiān)聽(tīng)器。當(dāng)用戶觸摸該控件時(shí),觸摸事件監(jiān)聽(tīng)器會(huì)被觸發(fā),并執(zhí)行相應(yīng)的操作。

示例代碼:

button.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        // 處理觸摸事件的邏輯代碼
        return true; // 返回true表示已經(jīng)處理了觸摸事件,false表示未處理
    }
});

button是要設(shè)置觸摸事件監(jiān)聽(tīng)器的視圖對(duì)象。setOnTouchListener方法接受一個(gè)View.OnTouchListener對(duì)象作為參數(shù),該對(duì)象實(shí)現(xiàn)了onTouch方法,用于處理觸摸事件。

在onTouch方法中,可以編寫(xiě)自定義的觸摸事件處理邏輯。根據(jù)MotionEvent對(duì)象的不同動(dòng)作(如按下、移動(dòng)、抬起等),可以執(zhí)行相應(yīng)的操作。最后,需要返回一個(gè)布爾值,表示是否已經(jīng)處理了觸摸事件。

使用setOnTouchListener方法可以實(shí)現(xiàn)各種觸摸事件的處理,例如拖動(dòng)、縮放、滑動(dòng)等。根據(jù)具體需求,可以在onTouch方法中編寫(xiě)相應(yīng)的代碼邏輯。


網(wǎng)頁(yè)名稱:Android事件分發(fā)機(jī)制
當(dāng)前地址:http://www.5511xx.com/article/djcgeoj.html