今天這篇文章主要分析的是Android的事件分發(fā)機制,采用例子加源碼的方式讓大家深刻的理解Android事件分發(fā)的具體情況,雖然網(wǎng)上很多Android的事件分發(fā)的文章,有些還寫的不錯,但是我還是決定寫這篇文章,用我自己的思維方式來幫助大家理解Android事件分發(fā),Android事件分發(fā)到底有多重要呢?相信很多Android開發(fā)者都明白吧,這個我就不介紹了,我也寫了很多篇文章里面涉及到Android的事件處理的問題,可能不理解Android事件分發(fā)的朋友會有點難理解吧,不過沒關(guān)系,相信看了這篇文章的你會對Android事件分發(fā)有進一步的理解。我這篇文章分析的源碼是Android 2.2的源碼, 也許你會說,干嘛不去分析最新的源碼呢?我這里要解釋一下,Android 2.2的源碼跟最新的源碼在功能效果方面是一樣的,只不過最新的源碼相對于Android 2.2來說更加健壯一些, Android 2.2的事件處理的代碼幾乎都寫在一個方法體里面,而最新的源碼分了很多個方法寫,如果用最新的源碼調(diào)用方法會繞來繞去的,相信你看的也會暈,出于這個考慮,我就拿Android 2.2的源碼來給大家分析。
我們提供的服務(wù)有:成都網(wǎng)站設(shè)計、做網(wǎng)站、微信公眾號開發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認證、高縣ssl等。為成百上千企事業(yè)單位解決了網(wǎng)站和推廣的問題。提供周到的售前咨詢和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的高縣網(wǎng)站制作公司
ViewGroup的事件分發(fā)機制
我們用手指去觸摸Android手機屏幕,就會產(chǎn)生一個觸摸事件,但是這個觸摸事件在底層是怎么分發(fā)的呢?這個我還真不知道,這里涉及到操作硬件(手機屏幕)方面的知識,也就是Linux內(nèi)核方面的知識,我也沒有了解過這方面的東西,所以我們可能就往上層來分析分析,我們知道Android中負責(zé)與用戶交互,與用戶操作緊密相關(guān)的四大組件之一是Activity, 所以我們有理由相信Activity中存在分發(fā)事件的方法,這個方法就是dispatchTouchEvent(),我們先看其源碼吧
public boolean dispatchTouchEvent(MotionEvent ev) { //如果是按下狀態(tài)就調(diào)用onUserInteraction()方法,onUserInteraction()方法 //是個空的方法, 我們直接跳過這里看下面的實現(xiàn) if (ev.getAction() == MotionEvent.ACTION_DOWN) { onUserInteraction(); } if (getWindow().superDispatchTouchEvent(ev)) { return true; } //getWindow().superDispatchTouchEvent(ev)返回false,這個事件就交給Activity //來處理, Activity的onTouchEvent()方法直接返回了false return onTouchEvent(ev); }
這個方法中我們還是比較關(guān)心getWindow()的superDispatchTouchEvent()方法,getWindow()返回當(dāng)前Activity的頂層窗口Window對象,我們直接看Window API的superDispatchTouchEvent()方法
/** * Used by custom windows, such as Dialog, to pass the touch screen event * further down the view hierarchy. Application developers should * not need to implement or call this. * */ public abstract boolean superDispatchTouchEvent(MotionEvent event);
這個是個抽象方法,所以我們直接找到其子類來看看superDispatchTouchEvent()方法的具體邏輯實現(xiàn),Window的唯一子類是PhoneWindow,我們就看看PhoneWindow的superDispattEvent()
public boolean superDispatchTouchEvent(KeyEvent event) { return mDecor.superDispatchTouchEvent(event); }
里面直接調(diào)用DecorView類的superDispatchTouchEvent方法,或許很多人不了解DecorView這個類,DecorView是PhoneWindow的一個final的內(nèi)部類并且繼承FrameLayout的,也是Window界面的最頂層的View對象,這是什么意思呢?別著急,我們接著往下看
我們先新建一個項目,取名AndroidTouchEvent,然后直接用模擬器運行項目, MainActivity的布局文件為
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:text="@string/hello_world" /> </RelativeLayout>
利用hierarchyviewer工具來查看下MainActivity的View的層次結(jié)構(gòu),如下圖
好了,就分析到這里吧,差不多分析完了,還有一種情況沒有分析到,例如我將CustomLayout的代碼改成下面的情形,Touch事件又是怎么分發(fā)的呢?我這里就不帶大家分析了
package com.example.androidtouchevent; import android.content.Context; import android.util.AttributeSet; import android.view.MotionEvent; import android.widget.RelativeLayout; public class CustomLayout extends RelativeLayout { public CustomLayout(Context context, AttributeSet attrs) { super(context, attrs, 0); } public CustomLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override public boolean onTouchEvent(MotionEvent event) { return super.onTouchEvent(event); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { if(ev.getAction() == MotionEvent.ACTION_MOVE){ return true; } return super.onInterceptTouchEvent(ev); } }
這篇文章的篇幅有點長,如果你想了解Touch事件的分發(fā)機制,你一定要認真看完,下面來總結(jié)一下吧
1.Activity的最頂層Window是PhoneWindow,PhoneWindow的最頂層View是DecorView
2.一個clickable或者longClickable的View會永遠消費Touch事件,不管他是enabled還是disabled的
3.View的長按事件是在ACTION_DOWN中執(zhí)行,要想執(zhí)行長按事件該View必須是longClickable的,并且不能產(chǎn)生ACTION_MOVE
4.View的點擊事件是在ACTION_UP中執(zhí)行,想要執(zhí)行點擊事件的前提是消費了ACTION_DOWN和ACTION_MOVE,并且沒有設(shè)置OnLongClickListener的情況下,如設(shè)置了OnLongClickListener的情況,則必須使onLongClick()返回false
5.如果View設(shè)置了onTouchListener了,并且onTouch()方法返回true,則不執(zhí)行View的onTouchEvent()方法,也表示View消費了Touch事件,返回false則繼續(xù)執(zhí)行onTouchEvent()
6.Touch事件是從最頂層的View一直分發(fā)到手指touch的最里層的View,如果最里層View消費了ACTION_DOWN事件(設(shè)置onTouchListener,并且onTouch()返回true 或者onTouchEvent()方法返回true)才會觸發(fā)ACTION_MOVE,ACTION_UP的發(fā)生,如果某個ViewGroup攔截了Touch事件,則Touch事件交給ViewGroup處理
7.Touch事件的分發(fā)過程中,如果消費了ACTION_DOWN,而在分發(fā)ACTION_MOVE的時候,某個ViewGroup攔截了Touch事件,就像上面那個自定義CustomLayout,則會將ACTION_CANCEL分發(fā)給該ViewGroup下面的Touch到的View,然后將Touch事件交給ViewGroup處理,并返回true
當(dāng)前名稱:Andriod從源碼的角度詳解View,ViewGroup的Touch事件的分發(fā)機制
文章分享:http://www.rwnh.cn/article22/pgsdcc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供Google、網(wǎng)站設(shè)計公司、網(wǎng)站維護、用戶體驗、電子商務(wù)、搜索引擎優(yōu)化
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)