Android好奇寶寶_08_亂侃觸摸事件傳遞

來源:互聯網
上載者:User

標籤:android   觸摸事件   

講解觸摸事件傳遞原理的網上有一大把,有從源碼角度講的,有從實際例子角度講的。我這裡呢只是記錄下自己的理解,講的可能沒其他大牛透徹,有錯誤的跪求評論指正。


直接,對照圖解和文字來分析觸摸事件的傳遞。


(1)亂七八糟圖解版:


(2)看圖說話:


(2.1)並不包含Activity,Activity沒有onInterceptTouchEvent方法,預設實現都是直接往下傳遞。


(2.2)講解3個觸摸事件控制方法的含義及其返回值的意義:


<1>onInterceptTouchEvent

onInterceptTouchEvent是ViewGroup特有的方法,Activity和View並沒有此方法,它的作用是用於攔截觸摸事件不再傳遞給子View(Activity和View並沒有子View,所以沒有此方法很符合邏輯),預設實現不攔截。如果攔截的話子View將完全接受不到觸摸事件,子View的任何相關觸摸事件的方法都不會被調用。(註:有例外情況我會在後面再說)(有特殊情況)

返回true:
表示攔截觸摸事件,不繼續調用子View的dispatchTouchEvent方法,直接調用自己的onTouchEvent方法。(有特殊情況)

返回false:
表示不攔截事件,繼續去調用子View的dispatchTouchEvent。


<2>dispatchTouchEvent

用於指派觸摸事件,注意是指派事件,而不是處理事件,這個方法應該做的是決定事件的傳遞方向,而不是處理消費掉觸摸事件。

返回true:

表示自己要消費這個事件,但並不是馬上消費,而是如果其子View沒人消費的話,則自己消費。事件還是會繼續往下傳遞的,只是在往上傳遞過程中如果還能到達自己的話,那麼就會去消費這個事件。

返回false:

表示自己不消費這個事件,如果同時onTouchEvent也返回false表示不消費這個事件的話,就會繼續往上傳遞給parent的onTouchEvent。


<3>onTouchEvent

用於處理事件,如果你想處理觸摸事件並做出相應的動作,那麼應該在這個方法中進行。

返回true:

表示自己想消費這個事件,並且馬上生效,即刻消費,事件傳遞停止。

返回false:

表示自己不想消費這個事件,同時檢查dispatchTouchEvent之前若是返回了true,就會發現:哎呀,我之前說子View沒人處理的話,那麼就我來處理。好吧,我要遵守諾言,就交給我處理吧,不要再傳遞了。


注意dispatchTouchEvent和onTouchEvent返回true的區別:


dispatchTouchEvent是沒人消費的話就交給我消費,你們都沒人要啊,那就給我吧,各位大爺真是好人啊。


onTouchEvent是我現在就要消費,其它人都沒份了,都幹嘛幹嘛去,就是這麼霸氣,就是這麼任性。


(2.3)傳遞過程中那些可能發生的事

觸摸事件的第一個接收者總是Activity,Activity一般不會去消費觸摸事件,而是直接傳遞給處於該觸摸事件範圍的View樹集合。在View樹中等級位置對應在觸摸事件中的位置,即越外層的View,就位于越頂層,而其child則位於底層。即Activity在最頂層,然後接下來是容器控制項,最後的View在最底層。


在一般情況下:

事件先從上往下,經過每一個dispatchTouchEvent。到達最後一個View時,調用其onTouchEvent,開始從下往上的傳遞過程,經過每一個onTouchEvent,這是沒任何View想要消費觸摸事件的情況。


可能發生的幾個轉折點:

<1>在從上往下的過程中,如果某個View的onInterceptTouchEvent返回了true,表示攔截事件,事件不會繼續往下傳遞,而是直接調用這個View的onTouchEvent,注意這並不意味著這個View消費了這個事件,只是攔截了這個事件繼續往下傳遞,剝奪了子View的消費權,提前開始從下往上的過程而已,是否由它消費還要看其onTouchEvent的返回值是否為true。(有特殊情況)


<2>在從下往上的過程中,如果某個View的onTouchEvent返回了true,表示自己想要消費這個事件,事件不會繼續往上傳遞,事件傳遞結束。


<3>還是在從下往上的過程中,如果某個View在之前的dispatchTouchEvent方法返回了true,表示在之前這個View表明如果所有子View都不消費這個事件的話,那麼就讓我來消費,事件不會繼續往上傳遞,事件傳遞結束。
(所有子View都不消費這個事件意味著所有子View的dispatchTouchEvent和onTouchEvent都返回了false,不然事件早被消費且傳遞結束了,根本不會再到達自己。)


<4>這個比較少用,某個子View調用了parent的requestDisallowInterceptTouchEvent方法,表示請求parent不要攔截事件,這種情況下parent的onInterceptTouchEvent返回了true也攔截不了事件,即讓onInterceptTouchEvent方法失效,這就是上面3個標記了(有特殊情況)所說的特殊情況。


(2.4)記憶功能

記憶功能是指,如果某個View消費了Down事件,那麼接下來的Move和Up等事件還是會從Activity頂層向下傳遞,但是傳遞到這個View時,即使這個View並沒有用onInterceptTouchEvent方法來攔截事件,事件還是會被攔截,直接由該View處理。即如果一個View消費了Down事件,則接下來的Move和Up事件也會交給它消費。

這麼做的原因是:一般情況下單一的觸摸事件並不能形成有效動作。比如一個拖動動作需要Down事件和連續的Move事件,點擊動作至少需要一個Down事件和Up事件。把單一的觸摸事件指派給不同的View,往往形成不了有意義的動作,所以加入了這個記憶功能來減少事件的傳遞。


(3)隨便說點

理解觸摸事件的傳遞一般是為瞭解決觸摸事件發生衝突的情況,處理觸摸事件衝突時要注意一點:

我們要處理的是由誰來處理觸摸事件,而不是去修改消費這個事件的View應該去怎麼處理。

有點拗口是吧,再說白一點就是我們應該控制誰來處理,而不是控制怎麼去處理,每個View都有自己的處理邏輯,我們不應該去修改它。
舉個栗子:
手指左右拖動不了ViewPager時,我們想得應該是怎麼在手指左右拖動的情況下讓ViewPager能獲得觸摸事件的消費權,而不要管接受到觸摸事件後怎麼讓ViewPager隨著手指滾動,這個功能ViewPager自己已經實現了,你把觸摸事件給它,它就能滾。


好了,本篇完結,建議對觸摸事件傳遞機制不熟悉的自己寫個例子列印些Log日誌驗證一下,再百度Google下一下常見的觸摸衝突及其解決辦法。


求贊求評論求指點啊!!!

Android好奇寶寶_08_亂侃觸摸事件傳遞

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.