1. 程式人生 > >一步步理解Android事件分發機制

一步步理解Android事件分發機制

回想一下,通常在Android開發中,我們最常接觸到的是什麼東西?顯然除了Activity以外,就是各種形形色色的控制元件(即View)了。
與此同時,一個App誕生的起因,終究是根據不同需求完成與使用者的各種互動。而所謂的互動,本質就是友好的響應使用者的各種操作行為。
所以說,有很多時候,一個控制元件(View)出現在螢幕當中,通常不會是僅僅為了擺設,而是還要能夠負責響應使用者的操作。
以最基本的例子而言:現在某一個介面中有一個按鈕(Button),而每當使用者點選了該按鈕,我們的程式將做出一定迴應。
那麼,如果我們還原“點選按鈕”這一行為,可以視作其根本實際就是:使用者的手指 與螢幕上該按鈕所處的位置發生了某種接觸。
所以簡單來說,我們可以將使用者每次與螢幕發生接觸,視作是一次“觸控事件”。而對於每次“觸控事件”的迴應處理,就構成了所謂的“互動”。
由此,也就引出了我們今天在此文裡想要弄清楚的一個知識點,即“Android的事件分發機制”。接著,我們就一步一步的來走進它。

為什麼需要分發?

在一切開始之前,我們先考慮一個問題。那就是為什麼我們發現 關於這個知識點總是被描述為“事件分發”而不是“事件處理”?試想以下情況:

小明註冊了一家公司開始了自己的創業之旅。這天,一位客戶上門為小明的公司帶來了第一單業務。我們可以將“這單業務”視作一次“觸控事件”。
小明樂壞了,趕緊開始著手這單業務。對應來說,我們可以理解為對“觸控事件”的處理。是的,目前為止我們都沒發現任何和“分發”相關的東西。
其實,我們不難想象到之所以沒有出現任何“分發”相關的東西,是因為現在公司只有小明獨自一人,除了自己處理,他別無它選。
對於“分發”這個詞本身就是以一定數量作為基礎的。比如小明的公司經過發展擴大到了十個人的規模,劃分了部門。這天又有新的業務來了。
這個時候小明就有很多選擇了,他可以選擇自己來處理這單業務;當然也可以選擇將業務派發下去讓員工來處理。這就是我們所謂的“分發”。

這個案例對應到Android中來說是一樣的,如果我們能保證當前螢幕上永遠只有唯一的一個View,那麼對於“觸控事件”的處理就沒什麼好說的了。
但顯然一個介面中通常都不會只有一個“獨苗”,它會涉及到不定量的View(ViewGroup)的組合。這個時候當“事件”發生,就不那麼容易處理了。
這其實也是為什麼,“Android的事件分發機制”是我們從菜鳥到進階的過程中繞不開必須掌握的一個知識點。
但實際上也沒關係,當我們明白了“小明創業”的這個例子,實際也就已經掌握了關於事件分發最基本的原理。

看事件如何分發?

我們說了所有與使用者發生互動的行為都是在手機螢幕,即某個介面中產生的。而Android的介面中的元素,無非就是View與ViewGroup。
與之同時,我們關注的另一個關鍵點是代表操作行為的“觸控事件”,這對應到英文中來說似乎就是“TouchEvent”。
OK,在我們目前兩眼一抹瞎的情況下。不妨試著以“TouchEvent”為關鍵字,到View與ViewGroup類中去研究研究相關的方法。

最終,我們單獨提出以下幾個需要我們理解的方法,它們也是事件分發機制的原理所在:

  • dispatchTouchEvent
  • onTouchEvent
  • onInterceptTouchEvent (只存在於ViewGroup)

好的,截止現在我們還不太明白這幾個方法的具體作用。只知道如果單獨從命名上看,它們似乎分別代表分發、處理和攔截類似的作用。

起源在哪?

從現在開始,我們要正式的一步步研究一個觸控事件的處理過程。我們先來看一個十分基礎但具有一定代表性的佈局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:tag="group_a"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:tag="group_b"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <Button
            android:tag="view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

    </LinearLayout>
</LinearLayout>

但如果是這樣,我們還是無法研究其事件的分發過程,所以我們自定義兩個類分別繼承LinearLayout以及Button類。
而我們要做的工作也很簡單,就是在我們之前提及的與“事件分發”相關的方法中,分別加上類似如下的日誌列印:

Log.d(getTag().toString(),”onTouchEvent”);

然後我們將佈局檔案中的LinearLayout和Button分別替換成我們自己定義的類,就搞定了。此時,我們執行程式後,對按鈕進行點選,得到如下日誌:

group_a: dispatchTouchEvent
group_a: onInterceptTouchEvent
group_b: dispatchTouchEvent
group_b: onInterceptTouchEvent
view: dispatchTouchEvent
view: onTouchEvent

一口氣吃不成一個胖子,我們這裡首先只關注一點,那就是:當我們點選按鈕後,最先被觸發的是“group_a“也就是最外層layout的dispatchTouchEvent方法。這個道理其實並不難理解,就像“小明創業”一樣,如果一單業務來臨,自然應該先由最高級別的“小明”知會。

也就是說,當一個“觸控事件”產生,將最先傳送到最頂層View。這看上去合情合理,但我們又不難想到,如果談到“最頂層”的話:
那麼,我們所有的View,即我們整個佈局檔案,它實際也有一個載體,那就是它的宿主Activity。因為你一定記得”setContenView(R.layout.xxx)”。
那麼,我們想象一下,“觸控事件”會不會最先被傳送到Activity呢?開啟Activity的原始碼我們驚喜的發現:它也包含dispatchTouchEvent和OnTouchEvent方法。OK,我們接著要做的,自然就是在我們的Activity類中覆寫這兩個方法,也加上日誌列印,再次執行測試得到如下日誌:

MainActivity: dispatchTouchEvent
group_a: dispatchTouchEvent
group_a: onInterceptTouchEvent
group_b: dispatchTouchEvent
group_b: onInterceptTouchEvent
view: dispatchTouchEvent
view: onTouchEvent

通過日誌,我們不難發現,正如我們推測的一樣,當觸控事件產生,的確是最先傳遞給Activity的。
這個時候,又要提到“小明”了。沒錯,當有業務來臨,肯定是先到達“公司”層面,然後才是最高負責人“小明”。

開啟Activity類的dispatchTouchEvent原始碼如下:

    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            onUserInteraction();
        }
        if (getWindow().superDispatchTouchEvent(ev)) {
            return true;
        }
        return onTouchEvent(ev);
    }

我們關注的重點放在下面一行程式碼上。由此,我們發現Activity接收到觸控事件後,是通過其所屬的Window來分發事件的。

if (getWindow().superDispatchTouchEvent(ev))

Window自身是一個抽象類,而其superDispatchTouchEvent也是一個抽象方法。其唯一實現存在PhoneWindow類中。
而在PhoneWindow當中,superDispatchTouchEvent的實現是這樣的:

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

也就是,這時候事件的分發會傳遞到mDecor,即Android檢視結構中所謂的“DecorView”當中,而DecorView自身本就是FrameLayout。
所以,這個時候事件分發的本質就很簡單了,它迴歸到了FrameLayout,即ViewGroup的事件分發。

P.S: DecorView涉及到了Android的UI介面架構的知識。我們通常可以最簡單的理解為一個Activiy就是一個介面。

但其實隨著對Android越來越熟悉,我們也可以很容易猜測到,實際上肯定不僅僅如此。那麼我們可以這樣簡單理解:

  • Activity會附屬在PhoneWindow上;這其中會首先包裹一個DecorView(翻譯就是裝飾檢視),它本身是一個FrameLayout。
    (所以,我們其實可以理解為,DecorView才是我們介面中真正位於最頂層的父View)
  • 而同時,通常來說,DecorView中會有兩個子View,分別是:TitleView及ContentView。
  • 其中,TitleView簡單來說就是我們平時所說的ActionBar(TitleBar)的那一列。而ContentView我們就熟悉了:“setContenView(R.layout.xxx)”

好了,話到這裡,我們先對我們目前的收穫進行總結,很簡單:
當一個“觸控事件”產生,會首先傳遞到當前Activity。Activity會通過其所屬Window,找到其中DecorView,從而開始逐級向下分發事件。

繼續傳遞

回憶我們點選按鈕時,所產生的輸出日誌:

MainActivity: dispatchTouchEvent
group_a: dispatchTouchEvent
group_a: onInterceptTouchEvent
group_b: dispatchTouchEvent
group_b: onInterceptTouchEvent
view: dispatchTouchEvent
view: onTouchEvent

我們發現,經由MainActivity進行傳遞,最終會首先到達該Activity的ContentView,即我們定義的佈局檔案中的最外層LinearLayou上。
這之後發生的事,我們通過日誌觀察的現象似乎是:事件在繼續向下傳遞,直到最後到達了最裡的Button,才通過onTouchEvent進行了處理。
所以,我們大膽猜測:一個“觸控事件”發生,會逐級dispatchTouchEvent,直至到達最底層的View,然後通過onTouchEvent進行處理。
這看上去是說得通的,但唯一的缺陷就在於,onInterceptTouchEvent 這個名字透露著攔截事件的方法,似乎並沒有得到什麼發揮?

那麼,我們乾脆直接開啟ViewGroup中onInterceptTouchEvent的原始碼:

    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return false;
    }

我們發現原始碼特別簡單,唯一值得注意的是,該方法有一個布林型的返回值,並且預設的返回值是false。
秉承著一貫的“手賤主義”的思想,我們將我們自定義的LinearLayou類中的onInterceptTouchEvent返回值修改為true。然後再次測試:

MainActivity: dispatchTouchEvent
group_a: dispatchTouchEvent
group_a: onInterceptTouchEvent
group_a: onTouchEvent

我們發現日誌列印已經發生了改變,通過日誌我們觀察到的是:事件傳遞到group_a後不再向下傳遞了,直接通過group_a的onTouchEvent進行處理。
這一現象其實是合理的,它告訴了我們:onInterceptTouchEvent的返回結果將決定事件是否被攔截在當前View層面。返回true則攔截;否則繼續傳遞。
而onInterceptTouchEvent的返回結果之所以能實現上述效果,可以在ViewGroup類中的dispatchTouchEvent方法裡找到答案。
ViewGroup當中的dispatchTouchEvent原始碼很多,也很複雜,我們很難去讀個透徹。但通過部分關鍵程式碼,我們可以知道它的原理是如下:
ViewGroup裡,dispatchTouchEvent裡會呼叫到onInterceptTouchEvent方法,並通過判斷其返回結果決定下一步操作:

  • 如果onInterceptTouchEvent返回true,則會呼叫onTouchEvent方法處理觸控事件。
  • 如果onInterceptTouchEvent返回false,則會通過child.dispatchTouchEvent的形式向下分發事件。

到現在,看上去我們基本已經對事件的整個分發流程都觸碰到了。但我們想象這樣一種情況:
小明的公司接收了一單新的業務,並分發給了底下的小王去做。但這時候的問題可能是:
小王收到通知後發現自己完成不了。或者說小王給出了一套方案,但他對該方案的信心並不足。
這樣的問題應該怎麼解決,很顯然,小王應該“報告老闆”。這單業務最後的處理方案可能還是得您來拿。

這對應到我們的程式中,應該如何來實現呢?我們發現,onTouchEvent這個方法也有一個布林型的返回值。
現在,我們試著將我們之前自定義的Button類裡的onTouchEvent的返回值修改為固定返回false。再次執行程式測試:

MainActivity: dispatchTouchEvent
group_a: dispatchTouchEvent
group_a: onInterceptTouchEvent
group_b: dispatchTouchEvent
group_b: onInterceptTouchEvent
view: dispatchTouchEvent
view: onTouchEvent
group_b: onTouchEvent
group_a: onTouchEvent

我們發現,事件在經過button類裡onTouchEvent處理後, 又回傳到上層目錄繼續處理了。
由此我們可以知道:onTouchEvent的返回值也是另一種“攔截”,不同的是之前我們說的是攔截事件繼續向下傳遞。
而這裡,是在表明,這個事件“我”是否能夠完全處理。如果能,則返回true,那麼事件經過“我”處理後就結束了。否則返回false,再讓父View去處理。

好了,這裡我們先總結一下到目前為止,我們掌握到的關於事件分發機制的流程:

  • 當一個觸控事件產生,會首先傳遞到其所屬Activity。Activity將負責將事件向下進行分發。
  • 該觸控事件將逐級的依次向下傳遞,直到傳遞至最底層View,然後進行處理。
  • ViewGroup在向下傳遞事件的時候,通過onInterceptTouchEvent的返回值來判斷是否攔截事件。
  • 如果確定攔截事件,那麼此次一系列的觸控事件都會通過該ViewGroup的onTouchEvent方法進行處理,並不再向下傳遞
  • onTouchEvent的返回結果決定了事件在此次處理之後,是否需要回傳到上一級的View。

好了,我們繼續看。我們肯定也注意到了,說了這麼多,但我們之前關於事件分發的重點,都是放在上一層View向下層View分發事件的過程。
也就是說,之前我們的重點是在分析ViewGroup的dispatchTouchEvent方法,我們說了該方法會判斷是否攔截事件,而決定是否繼續向下傳遞事件。
當就拿我們此文中的例子來說,當事件最終傳遞到button類當中。我們不難想象到,這時dispatchTouchEvent的工作肯定與之前有所不同。
因為Button自身只是一個View,它不會存在所謂的子檢視。也就說,這個時候事件你肯定要做出處理了,那麼還分發個什麼勁呢?

要得到這個問題的答案,最好的方式當然就是開啟View類裡的dispatchTouchEvent方法的原始碼看看,這裡我們只擷取我們關心的程式碼部分:

        if (onFilterTouchEventForSecurity(event)) {
            //noinspection SimplifiableIfStatement
            ListenerInfo li = mListenerInfo;
            if (li != null && li.mOnTouchListener != null
                    && (mViewFlags & ENABLED_MASK) == ENABLED
                    && li.mOnTouchListener.onTouch(this, event)) {
                result = true;
            }

            if (!result && onTouchEvent(event)) {
                result = true;
            }
        }

我們看到,首先會獲取一個ListenerInfo型別的變數。該型別實際就是封裝了各種型別的Listener。隨後會開啟第一次判斷:
如果此物件不為空,mOnTouchListener不為空,且(mViewFlags & ENABLED_MASK) ==ENABLED,則會執行mOnTouchListener。
這其中(mViewFlags & ENABLED_MASK) ==ENABLED是判斷控制元件狀態是否是ENABLE的,預設情況肯定是的。
mOnTouchListener看著有些眼熟,如果我們檢視原始碼,你就更眼熟了,因為我們發現它是通過如下程式碼進行賦值的:

    public void setOnTouchListener(OnTouchListener l) {
        getListenerInfo().mOnTouchListener = l;
    }

接著看程式碼,我們發現如果li.mOnTouchListener.onTouch(this, event)執行的結果也為true,那麼result也將被設定為true。
假設該方法的執行結果返回是false,那麼以上程式碼將繼續進行,從而開始第二輪判斷,於是onTouchEvent方法得以執行。

OK,對於這裡的程式碼,我覺得有兩點是值得一說的。第一是,我們首先可以明白如下的結論:

  • 假如我們為某個View設定了OnTouchListener,那麼listener會先於onTouchEvent執行。同時:
  • 如果listener的onTouch方法返回true,那麼onTouchEvent將不再執行。

第二點是,我們看到對於View來說:假設onTouchEvent的返回值為false,那麼dispatchTouchEvent也會返回false。
這實際上就構成了整個“onTouchEvent返回值可以決定事件是否回傳”的原因。這是因為:
ViewGroup在通過child.dispatchTouchEvent向下分發事件時,會通過該返回值來判斷子檢視是否具備處理事件的能力。
如果返回為false,就會繼續遍歷子檢視,直至遍歷到有一個具備事件處理能力的子檢視為止。
如果沒有一個具備處理能力的子檢視,那麼ViewGroup就會自己通過onTouchEvent來解決了。

到了這裡,我們實際上已經對整個Android事件的分發機制有了不錯的瞭解了。但我們肯定會想到一個問題:
那就是,以Button來說,我們通常是通過setOnClickListener的方式來對其設定點選事件監聽的。
但很顯然,我們目前為止研究過的程式碼中,還沒有出現任何與之相關的東西。在View類中,我們剩下沒有看過程式碼的,就是onTouchEvent了:

        if (((viewFlags & CLICKABLE) == CLICKABLE ||
                (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) ||
                (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE) {
            switch (action) {
                case MotionEvent.ACTION_UP:
                    boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
                    if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
                        // take focus if we don't have it already and we should in
                        // touch mode.
                        boolean focusTaken = false;
                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
                            focusTaken = requestFocus();
                        }

                        if (prepressed) {
                            // The button is being released before we actually
                            // showed it as pressed.  Make it show the pressed
                            // state now (before scheduling the click) to ensure
                            // the user sees it.
                            setPressed(true, x, y);
                       }

                        if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
                            // This is a tap, so remove the longpress check
                            removeLongPressCallback();

                            // Only perform take click actions if we were in the pressed state
                            if (!focusTaken) {
                                // Use a Runnable and post this rather than calling
                                // performClick directly. This lets other visual state
                                // of the view update before click actions start.
                                if (mPerformClick == null) {
                                    mPerformClick = new PerformClick();
                                }
                                if (!post(mPerformClick)) {
                                    performClick();
                                }
                            }
                        }

以上程式碼是我們關心的原因所在,我們看到經過一系列的判斷後,會進入到一個名為performClick的方法呼叫,開啟該方法的原始碼:

    public boolean performClick() {
        final boolean result;
        final ListenerInfo li = mListenerInfo;
        if (li != null && li.mOnClickListener != null) {
            playSoundEffect(SoundEffectConstants.CLICK);
            li.mOnClickListener.onClick(this);
            result = true;
        } else {
            result = false;
        }

        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
        return result;
    }

綜合以上兩段程式碼,我們可以得出以下結論:

  • onClickListener會在onTouchEvent方法中,ACTION為UP的時候得以執行。
  • 但注意前提條件是,控制元件是可點選(長按)的;並且mOnClickListener不為空。

最後的總結與比喻

最後,我們仍舊以“小明創業“的例子來總結我們所學到的關於Android的事件分發的相關知識。

  • 公司(Activity)接收了一項新的業務(觸控事件)。
  • 該業務會最先到達公司的最高層小明手上(最頂層View)。
  • 小明研究了以下此次業務,此時可以分為兩種情況:
    1、小明認為此業務難度不大,於是決定將業務分配給部門經理小王(dispatch-event)。
    2、小明認為此次業務至關重要,決定自己處理(intercept-event & onTouchEvent)。
  • 假設業務分配給了經理小王,此時小王與小明一樣,同樣有兩種選擇:即自己攔截處理或者繼續向下佈置。
  • 業務最終終將被分配到某個員工的手中,它會負責處理(onTouchEvent)。
  • 但該員工接收到任務後,也可以判斷自己是否能夠完成,如果覺得不能完成,
    或者還需要上級稽核,可以選擇回報給上級(onTouchEvent返回false)
  • 員工處理該任務的方式也許有多種,例如A(OnTouchListener)、B(onTouchEvent)、C(OnClickListener) 等等。
    (它們的優先順序順序是 A > B > C 。。。。 )

相關推薦

步步理解Android事件分發機制

回想一下,通常在Android開發中,我們最常接觸到的是什麼東西?顯然除了Activity以外,就是各種形形色色的控制元件(即View)了。 與此同時,一個App誕生的起因,終究是根據不同需求完成與使用者的各種互動。而所謂的互動,本質就是友好的響應使用者的各種

站在大神肩膀上,深入理解 Android事件分發機制

Android事件分發,參考了網上的很多資料。基本基於android2.2的原始碼來分析,因為即使是新的版本,裡面的原理思想也沒有改變。 有了大神的肩膀,我在理解了其原理的基礎上,進行一個小總結。 先理解一個概念: 事件:在android中,點選螢幕是時,產生的長按,點選

Android事件分發機制 系統預設機制

1.為什麼要了解Android事件機制? 背景:我在做Android專案的時候遇到一個Activity->Fragment->ScrollView->Button這樣的巢狀關係,當一切都準備就緒,程式啟動後點擊Button的時候系統異常崩潰了,騰訊Bugl

Android事件分發機制完全解析,帶你從原始碼的角度徹底理解(上)-郭霖

其實我一直準備寫一篇關於Android事件分發機制的文章,從我的第一篇部落格開始,就零零散散在好多地方使用到了Android事件分發的知識。也有好多朋友問過我各種問題,比如:onTouch和onTouchEvent有什麼區別,又該如何使用?為什麼給ListView引入了一

Android事件分發機制完全解析,帶你從原始碼的角度徹底理解(下)-郭霖

記得在前面的文章中,我帶大家一起從原始碼的角度分析了Android中View的事件分發機制,相信閱讀過的朋友對View的事件分發已經有比較深刻的理解了。 還未閱讀過的朋友,請先參考 Android事件分發機制完全解析,帶你從原始碼的角度徹底理解(上) 。 那麼今天我們將繼

關於Android事件分發機制的巨集觀理解(簡單)

我儘量不打錯別字,用詞準確,不造成閱讀障礙。 之所以說是巨集觀,是因為我不會寫demo,一步步截圖給你看,我會拿原始碼然後剔除暫時用不到的部分,讓你從大脈絡上理解事件分發機制,這樣你會發現,很簡單。 首先在腦海中應該有一個例子,一個LinearLayout裡

Android事件分發機制完全解析,帶你從原始碼的角度徹底理解(上)

其實我一直準備寫一篇關於Android事件分發機制的文章,從我的第一篇部落格開始,就零零散散在好多地方使用到了Android事件分發的知識。也有好多朋友問過我各種問題,比如:onTouch和onTouchEvent有什麼區別,又該如何使用?為什麼給ListView引入

Android事件分發機制完全解析,帶你從原始碼的角度徹底理解(下)

記得在前面的文章中,我帶大家一起從原始碼的角度分析了Android中View的事件分發機制,相信閱讀過的朋友對View的事件分發已經有比較深刻的理解了。那麼今天我們將繼續上次未完成的話題,從原始碼的角度分析ViewGroup的事件分發。首先我們來探討一下,什麼是ViewGro

張圖搞懂android事件分發機制

        事件分發機制在安卓中非常重要,這個事情如果搞不懂,會困擾你很多事情。比如說,應用了github上的某個大神的庫,如果發現這個庫實現了你需求的80%,還有那麼20%需要你結合實際需求來實現

讀《android開發藝術探索》筆記:View的事件分發機制

View的事件分發機制:對於一個根viewgroup來說,點選事件產生後,首先會傳遞給它,這是它的dispatchTouchEvent就會被呼叫,如果這個viewGroup的OnInterceptTouchEvent方法返回true就表示它要攔截當前事件,接著事

android 事件分發機制 概念理解

android 事件分發機制 參考資料 Android 事件分發機制原始碼和例項解析 Android View 事件分發機制詳解 圖解 Android 事件分發機制 圖解View的事件分發機制 原理 分發事件 的起始點: 從 Act

淺談Android 事件分發機制

get touch 需要 傳遞 cimage android ges 常見 滑動 在上一篇文章中,淺談Android 事件分發機制(一),簡要分析了一下事件分發機制的原理,總結一下就是事件層層傳遞,直到被消費,原理看似簡單,但是在實際使用過程中,場景各不相同,復雜程度也就因

Android事件分發機制完全解析,帶你從原始碼的角度徹底理解(下) (出自郭林老師)

記得在前面的文章中,我帶大家一起從原始碼的角度分析了Android中View的事件分發機制,相信閱讀過的朋友對View的事件分發已經有比較深刻的理解了。 那麼今天我們將繼續上次未完成的話題,從原始碼的角度分析ViewGroup的事件分發。 首先我們來探討一下,什

Android事件分發機制——View()

/**      * Implement this method to handle touch screen motion events.      *      * @param event The motion event.      * @return True if the event was

Android事件分發機制完全解析,帶你從原始碼的角度徹底理解(上) (出自郭霖老師)

其實我一直準備寫一篇關於Android事件分發機制的文章,從我的第一篇部落格開始,就零零散散在好多地方使用到了Android事件分發的知識。也有好多朋友問過我各種問題,比如:onTouch和onTouchEvent有什麼區別,又該如何使用?為什麼給ListView引入了

Android事件分發機制事件是如何到達activity的?

> 事件分發,真的一定從Activity開始嗎? ## 前言 很高興遇見你~ 事件分發,android中一個老生常談的話題了。基本的流程我們也都知道是從Activity開始分發,但有一個關鍵問題是:**事件是如何到達Activity的** ? 你以為我接下來要開始講原始碼、系統底層了?不不不,本文不講

android 事件分發機制

cnblogs instance 1.0 必須 div called tool per 測試環境 我們通過代碼來分析 package im.weiyuan.com.viewutils; import android.content.Intent; import

Android 事件分發機制 圖解

ack 理解 cnblogs png ont tor 自己的 block ans 在Android 開發中事件分發是比較重要的,也是比較難理解的,之前看過這方面的東西,以為自己弄懂了,也就沒太註意,最近面試呢,想著肯定要問到這一塊的東西,回顧的時候發現

從小白角度探索Android事件分發機制

https 事件 很好 tar 上班 bsp 備份 http nbsp 今早來上班時看到郭神這邊文章超贊,劇情很好引人入勝,特此備份! https://mp.weixin.qq.com/s?__biz=MzA5MzI3NjE2MA==&mid=2650244386&

Android事件分發機制

前言 Android事件分發機制是Android開發者必須瞭解的基礎 網上有大量關於Android事件分發機制的文章,但存在一些問題:內容不全、思路不清晰、無原始碼分析、簡單問題複雜化等等 今天,我將全面總結Android的事件分