Android View 事件傳遞機制剖析
View事件傳遞 touch事件分發
學習Android一年有餘,今天開始以自己的理解去介紹一下Android開發常用到的基礎技術。第一個介紹的是View 的事件傳遞機制,建議首先去看一下[codeKK中關於View事件傳遞介紹的文章][1],我這裡只是對這個的補充以及自己理解。有不正確的地方歡迎拍 磚☺。
第一部分:知識儲備
- 在Android中所有的TouchEvent事件都封裝在MotionEvent物件中,而TouchEvent事件主要包括Touch的位置,時間,歷史記錄,滑動等等。
- 常見MotionEvent的型別包括:ACTION_DOWN,ACTION_MOVE,ACTION_CANCEL,ACTION_UP,ACTION_SCROLL等等。
- 我們關心的對事件的處理實質上就是 dispatchTouchEvent,onTouchEvent,onInterceptTouchEvent這三個函式,分別代表事件傳遞,事件消費 和事件攔截的意思,這三個函式都是boolean型別的,如果返回值為true代表該事件被消耗。
(註明:以上的內容是從codeKK文章中部分摘取的)
第二部分:實戰演練
以我的理解,要掌握整個事件的傳遞過程,必須得理清楚那三個事件處理函式,最好是自己寫寫程式碼驗證一下。 以下我根據事件的消耗分四個部分:不攔截不消費,不攔截消費,攔截不消費,攔截消費。為了更好的理解,假設佈局層次如下:
這個是在UI Automator中的截圖,佈局很簡單,最外層為一個LinearLayout,然後巢狀了兩個LinearLayout。在這個裡為了方便我簡稱為從最外到裡分別為L0,L1,L2。其預覽圖如下:
佈局檔案如下:
<?xml version="1.0" encoding="utf-8"?> <com.example.TouchEventDemo.MyLinearLayout0 xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/L0" android:background="@android:color/white" > <com.example.TouchEventDemo.MyLinearLayout1 android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/L1" android:layout_margin="20dp" android:background="@android:color/holo_blue_dark" > <com.example.TouchEventDemo.MyLinearLayout2 android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/L2" android:background="@android:color/holo_red_light" android:layout_margin="20dp" android:orientation="horizontal" /> </com.example.TouchEventDemo.MyLinearLayout1> </com.example.TouchEventDemo.MyLinearLayout0>
這裡為了更好的看清楚事件的傳遞,我們需要自定義三個LinearLayout,並重寫三個事件函式,dispatchTouchEvent,onTouchEvent,onInterceptTouchEvent
@Override public boolean dispatchTouchEvent(MotionEvent ev) { Log.i(TAG, "MyLinearLayout0------------dispatchTouchEvent"); return super.dispatchTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { Log.i(TAG, "MyLinearLayout0------------onTouchEvent"); return super.onTouchEvent(event); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { Log.i(TAG, "MyLinearLayout0------------onInterceptTouchEvent"); return super.onInterceptTouchEvent(ev); }
好了,前期準備工作已經完成,我們開始驗證:
1.不攔截不消費:
即所有的onTouchEvent,onInterceptTouchEvent函式返回為fasle。預期的流程應該是:
當我們點選L2即紅色區域程式執行的結果是:
可以看到和我們預期的一模一樣。
2.不攔截消費:
這裡假定L1對事件不攔截消費,即L1.onInterceptTouchEvent位false,L1.onTouchEvent返回為true,說明L1對消費了事件,且沒有攔截事件。同樣我們的預期流程應該有兩種情況: 第一種:L2消費掉事件,即L2.onTouchEvent返回為true,其流程應該是:
當我們點選L2即紅色區域程式執行的結果是:
第二種:L2沒有消費掉事件,即L2.onTouchEvent返回為fasle,其流程應該是:
當我們點選L2即紅色區域程式執行的結果是:
到這裡前兩種情況基本介紹完了,總結下,在這裡最重要的一點要記住,如果子VIEW沒有消費掉ACTION_DOWN的事件,則後續的UP/MOVE事件將不會到來。
3.攔截不消費:
這裡假定的物件還是L1,即L1對事件攔截但不消費,即L1.onInterceptTouchEvent位true,L1.onTouchEvent返回為false。從字面上可以L1攔截了事件,則L2是不會在接受到任何事件的。預期的流程應該是:
當我們點選L2即紅色區域程式執行的結果是:
可以看到和我們流程圖是一樣的。
4.攔截消費:
這裡假定的對還是L1,即L1對事件攔截且消費,即L1.onInterceptTouchEvent位true,L1.onTouchEvent返回為true。預期的流程應該是:
當我們點選L2即紅色區域程式執行的結果是:
執行結果和流程圖一樣
第三部分:總結
以上就是就是view事件傳遞的流程,當然還沒有包括點選,長按等事件。下面對全文做個總結: (1) 事件從 Activity.dispatchTouchEvent()開始傳遞,只要沒有被停止或攔截,從最上層的 View(ViewGroup)開始一直往下(子 View)傳遞。子 View 可以通過 onTouchEvent()對事件進行處理。
(2) 事件由父 View(ViewGroup)傳遞給子 View,ViewGroup 可以通過 onInterceptTouchEvent()對事件做攔截,停止其往下傳遞。
(3) 如果事件從上往下傳遞過程中一直沒有被停止,且最底層子 View 沒有消費事件,事件會反向往上傳遞,這時父 View(ViewGroup)可以進行消費,如果還是沒有被消費的話,最後會到 Activity 的 onTouchEvent()函式。
(4) 如果 View 沒有對 ACTION_DOWN 進行消費,之後的其他事件不會傳遞過來。
(5) OnTouchListener 優先於 onTouchEvent()對事件進行消費。
原始碼:連結:http://pan.baidu.com/s/1sjsUmsP 密碼:v6lp
相關文章
- Android事件傳遞機制Android事件
- Android TouchEvent事件傳遞機制Android事件
- Android onTouch事件傳遞機制Android事件
- Android Touch事件傳遞機制全面解析(從WMS到View樹)Android事件View
- Android觸控事件傳遞機制Android事件
- Android10_原理機制系列_事件傳遞機制Android事件
- View 事件傳遞體系知識梳理(1) 事件分發機制View事件
- Android從原始碼角度剖析View事件分發機制Android原始碼View事件
- 【朝花夕拾】Android自定義View篇之(五)Android事件分發及傳遞機制AndroidView事件
- Android中觸控事件的傳遞機制Android事件
- 初識Android觸控事件傳遞機制Android事件
- Android Touch事件傳遞機制通俗講解Android事件
- Android學習之 Touch事件傳遞機制Android事件
- 快速理解android事件傳遞攔截機制概念Android事件
- Android View 的事件體系 -- 事件分發機制AndroidView事件
- View事件機制分析View事件
- Android View事件機制 21問21答AndroidView事件
- 用一張圖告訴你Android中的事件傳遞機制Android事件
- 【Android原始碼】View的事件分發機制Android原始碼View事件
- View事件分發機制View事件
- Android 事件分發機制原始碼解析-view層Android事件原始碼View
- 10分鐘理解 Android View 事件分發機制AndroidView事件
- 圖片會說話系列之Android事件的分發傳遞機制Android事件
- View事件分發機制分析View事件
- Android Handler訊息傳遞機制詳解Android
- Android觸控事件傳遞機制及viewpager巢狀fragment衝突處理Android事件Viewpager巢狀Fragment
- Android自定義View之事件分發機制總結AndroidView事件
- 基於原始碼分析 Android View 事件分發機制原始碼AndroidView事件
- 《Android開發藝術探索》——View事件分發機制AndroidView事件
- Android事件分發:從原始碼角度分析View事件分發機制Android事件原始碼View
- iOS中觸控事件的傳遞和響應機制iOS事件
- 探索View的事件分發機制View事件
- View的事件分發機制分析View事件
- Zookeeper watcher 事件機制原理剖析事件
- Android之Handler訊息傳遞機制詳解Android
- Android訊息傳遞之Handler訊息機制Android
- Android 事件機制Android事件
- iOS 中的事件傳遞和響應機制 - 原理篇iOS事件