在安卓四大組件中(Activity
、Service
、BroadCast
、ContentProvider
),最經常使用的當是Activity
。由於Activity
負責提供直觀的頁面並響應用戶操做。在Activity
的佈局文件中,經過最外層的ViewGroup
(佈局)一層層嵌套、佈局直至View
(控件),組成了豐富多彩的用戶頁面。如QQ、微信等等。在開發這些頁面過程當中,不免會遇到一些事件衝突(說人話就是:你想點擊的某個佈局或控件,發現響應的是另外一個佈局或控件)的問題。呵呵,怎麼辦呢?由此引入咱們接下來討論的問題。git
手機在響應用戶的點擊操做時,從Activity
入口,遵循着必定的規則將對應的事件交由指定的ViewGroup
或者View
去響應(消費這個事件)。只有找出了各中規則,往後再次處理這類事件問題時,一定會駕輕就熟。從程序的角度來看,Android
提供三個方法處理事件問題dispatchTouchEvent
(分發點擊事件)、onInterceptTouchEvent
(攔截點擊事件),onTouchEvent
(處理點擊事件)。每一個方法返回true
或false
表示是否處理它對應的職責。好比說,若是我攔截了事件,就表示自身要處理該事件,不讓別的控件再能接收到事件信號。除了返回true
或false
以外,還能經過調用父類的方法執行父類的邏輯。簡而言之,Activity
、ViewGroup
、View
三個類處理事件,相關的方法依次是dispatchTouchEvent
、onInterceptTouchEvent
、onTouchEvent
以及每一個方法的返回能夠是true
、false
和super
。其中注意:Activity
和View
沒有攔截事件方法。github
編寫一個測試demo,佈局文件中用LinearLayout
嵌套RelativeLayout
,最後在RelativeLayout
中包含一個Button
按鈕。依次在每一個事件處理方法中,輸出log日誌。點擊按鈕測試,經過日誌信息分析事件分發流程。下圖是佈局效果。微信
爲方便描述,定製命名規則:Activity
簡寫A,LinearLayout
簡寫L,RelativeLayout
簡寫R,Button
簡寫B,dispatchTouchEvent
簡寫D,onInterceptTouchEvent
簡寫I,onTouchEvent
簡寫T,返回true
簡寫T,返回false
簡寫F,返回super
簡寫S。如:ADS表示Activity
中dispatchTouchEvent
方法 return super
。ide
ADS/ATS、LDS/LIS/LTS、RDS/RIS/RTS、BDS/BTS
複製代碼
日誌說明佈局
04-01 12:44:44.402: D/Activity(1234): dispatchTouchEvent ACTION_DOWN
04-01 12:44:44.402: D/MyLinearLayout(1234): dispatchTouchEvent ACTION_DOWN
04-01 12:44:44.402: D/MyLinearLayout(1234): onInterceptTouchEvent ACTION_DOWN
04-01 12:44:44.402: D/MyRelativeLayout(1234): dispatchTouchEvent ACTION_DOWN
04-01 12:44:44.402: D/MyRelativeLayout(1234): onInterceptTouchEvent ACTION_DOWN
04-01 12:44:44.402: D/MyButton(1234): dispatchTouchEvent ACTION_DOWN
04-01 12:44:44.402: D/MyButton(1234): onTouchEvent ACTION_DOWN
04-01 12:44:44.506: D/Activity(1234): dispatchTouchEvent ACTION_UP
04-01 12:44:44.506: D/MyLinearLayout(1234): dispatchTouchEvent ACTION_UP
04-01 12:44:44.506: D/MyLinearLayout(1234): onInterceptTouchEvent ACTION_UP
04-01 12:44:44.506: D/MyRelativeLayout(1234): dispatchTouchEvent ACTION_UP
04-01 12:44:44.506: D/MyRelativeLayout(1234): onInterceptTouchEvent ACTION_UP
04-01 12:44:44.506: D/MyButton(1234): dispatchTouchEvent ACTION_UP
04-01 12:44:44.506: D/MyButton(1234): onTouchEvent ACTION_UP
04-01 12:44:44.506: D/Button(1234): 點擊
複製代碼
整理出以下示意圖:三色箭頭實線,表示對應方法返回一個值會跳轉到下一個方法。其中Button 返回true和返回super都會消費事件,只是返回true就不在就再也不響應button的點擊事件。測試
ADS/ATS、LDS/LIS/LTS、RDS/RIS/RTS、BDS/BTF
複製代碼
日誌說明spa
04-01 14:00:54.970: D/Activity(1387): dispatchTouchEvent ACTION_DOWN
04-01 14:00:54.970: D/MyLinearLayout(1387): dispatchTouchEvent ACTION_DOWN
04-01 14:00:54.970: D/MyLinearLayout(1387): onInterceptTouchEvent ACTION_DOWN
04-01 14:00:54.970: D/MyRelativeLayout(1387): dispatchTouchEvent ACTION_DOWN
04-01 14:00:54.970: D/MyRelativeLayout(1387): onInterceptTouchEvent ACTION_DOWN
04-01 14:00:54.970: D/MyButton(1387): dispatchTouchEvent ACTION_DOWN
04-01 14:00:54.970: D/MyButton(1387): onTouchEvent ACTION_DOWN
04-01 14:00:54.970: D/MyRelativeLayout(1387): onTouchEvent ACTION_DOWN
04-01 14:00:54.970: D/MyLinearLayout(1387): onTouchEvent ACTION_DOWN
04-01 14:00:54.970: D/Activity(1387): onTouchEvent ACTION_DOWN
04-01 14:00:55.066: D/Activity(1387): dispatchTouchEvent ACTION_UP
04-01 14:00:55.066: D/Activity(1387): onTouchEvent ACTION_UP
複製代碼
說明:Button 的onTouchEvent return false時,點擊事件會返回到上一層視圖。若是一直都沒有控件處理這個事件就會交給Activitiy 的onTouchEvent消費。當再傳入事件時,不會再按照以前的流程,每一個空間均處理一次,而是直接給 Activity 的onTouchEvent消費。就是虛線所指。3d
ADS/ATS、LDS/LIS/LTS、RDS/RIS/RTS、BDT/BTF
複製代碼
日誌說明日誌
04-01 14:12:47.918: D/Activity(1444): dispatchTouchEvent ACTION_DOWN
04-01 14:12:47.918: D/MyLinearLayout(1444): dispatchTouchEvent ACTION_DOWN
04-01 14:12:47.918: D/MyLinearLayout(1444): onInterceptTouchEvent ACTION_DOWN
04-01 14:12:47.918: D/MyRelativeLayout(1444): dispatchTouchEvent ACTION_DOWN
04-01 14:12:47.918: D/MyRelativeLayout(1444): onInterceptTouchEvent ACTION_DOWN
04-01 14:12:47.918: D/MyButton(1444): dispatchTouchEvent ACTION_DOWN
04-01 14:12:48.030: D/Activity(1444): dispatchTouchEvent ACTION_UP
04-01 14:12:48.030: D/MyLinearLayout(1444): dispatchTouchEvent ACTION_UP
04-01 14:12:48.030: D/MyLinearLayout(1444): onInterceptTouchEvent ACTION_UP
04-01 14:12:48.030: D/MyRelativeLayout(1444): dispatchTouchEvent ACTION_UP
04-01 14:12:48.030: D/MyRelativeLayout(1444): onInterceptTouchEvent ACTION_UP
04-01 14:12:48.030: D/MyButton(1444): dispatchTouchEvent ACTION_UP
複製代碼
說明:Button dispatchTouchEvent方法返回true,表示自身須要消費該事件。且不傳遞給onTouchEvent方法。code
ADS/ATS、LDS/LIS/LTS、RDS/RIS/RTS、BDF/BTF
複製代碼
日誌說明
04-01 14:19:40.014: D/Activity(1502): dispatchTouchEvent ACTION_DOWN
04-01 14:19:40.014: D/MyLinearLayout(1502): dispatchTouchEvent ACTION_DOWN
04-01 14:19:40.014: D/MyLinearLayout(1502): onInterceptTouchEvent ACTION_DOWN
04-01 14:19:40.014: D/MyRelativeLayout(1502): dispatchTouchEvent ACTION_DOWN
04-01 14:19:40.014: D/MyRelativeLayout(1502): onInterceptTouchEvent ACTION_DOWN
04-01 14:19:40.014: D/MyButton(1502): dispatchTouchEvent ACTION_DOWN
04-01 14:19:40.014: D/MyRelativeLayout(1502): onTouchEvent ACTION_DOWN
04-01 14:19:40.014: D/MyLinearLayout(1502): onTouchEvent ACTION_DOWN
04-01 14:19:40.014: D/Activity(1502): onTouchEvent ACTION_DOWN
04-01 14:19:40.022: D/Activity(1502): dispatchTouchEvent ACTION_UP
04-01 14:19:40.022: D/Activity(1502): onTouchEvent ACTION_UP
複製代碼
說明:Button dispatchTouchEvent方法返回false,事件傳遞給父控件onTouchEvent方法。
ADS/ATS、LDS/LIS/LTS、RDS/RIS/RTT、BDF/BTF
複製代碼
日誌說明
04-01 14:26:03.306: D/Activity(1561): dispatchTouchEvent ACTION_DOWN
04-01 14:26:03.306: D/MyLinearLayout(1561): dispatchTouchEvent ACTION_DOWN
04-01 14:26:03.306: D/MyLinearLayout(1561): onInterceptTouchEvent ACTION_DOWN
04-01 14:26:03.306: D/MyRelativeLayout(1561): dispatchTouchEvent ACTION_DOWN
04-01 14:26:03.306: D/MyRelativeLayout(1561): onInterceptTouchEvent ACTION_DOWN
04-01 14:26:03.306: D/MyButton(1561): dispatchTouchEvent ACTION_DOWN
04-01 14:26:03.306: D/MyRelativeLayout(1561): onTouchEvent ACTION_DOWN
04-01 14:26:03.366: D/Activity(1561): dispatchTouchEvent ACTION_UP
04-01 14:26:03.366: D/MyLinearLayout(1561): dispatchTouchEvent ACTION_UP
04-01 14:26:03.366: D/MyLinearLayout(1561): onInterceptTouchEvent ACTION_UP
04-01 14:26:03.366: D/MyRelativeLayout(1561): dispatchTouchEvent ACTION_UP
04-01 14:26:03.366: D/MyRelativeLayout(1561): onTouchEvent ACTION_UP
複製代碼
說明:RelativeLayout 的onTouchEvent方法return true 消費了事件,下次事件生成時,就不傳遞給Button,直接交由RelativeLayout 的onTouchEvent方法處理。
ADS/ATS、LDS/LIS/LTS、RDS/RIS/RTF、BDF/BTF
複製代碼
日誌說明
04-01 14:39:20.794: D/Activity(1644): dispatchTouchEvent ACTION_DOWN
04-01 14:39:20.798: D/MyLinearLayout(1644): dispatchTouchEvent ACTION_DOWN
04-01 14:39:20.798: D/MyLinearLayout(1644): onInterceptTouchEvent ACTION_DOWN
04-01 14:39:20.798: D/MyRelativeLayout(1644): dispatchTouchEvent ACTION_DOWN
04-01 14:39:20.798: D/MyRelativeLayout(1644): onInterceptTouchEvent ACTION_DOWN
04-01 14:39:20.798: D/MyButton(1644): dispatchTouchEvent ACTION_DOWN
04-01 14:39:20.798: D/MyRelativeLayout(1644): onTouchEvent ACTION_DOWN
04-01 14:39:20.798: D/MyLinearLayout(1644): onTouchEvent ACTION_DOWN
04-01 14:39:20.798: D/Activity(1644): onTouchEvent ACTION_DOWN
04-01 14:39:20.874: D/Activity(1644): dispatchTouchEvent ACTION_UP
04-01 14:39:20.874: D/Activity(1644): onTouchEvent ACTION_UP
複製代碼
說明:RelativeLayout return false,就會將事件傳遞到上一層控件消費。其中,RelativeLayout onInterceptTouchEvent return false 表示事件也會分發到Button處理。
ADS/ATS、LDS/LIS/LTS、RDS/RIT/RTF、BDF/BTF
複製代碼
日誌說明
04-01 15:02:41.594: D/Activity(1739): dispatchTouchEvent ACTION_DOWN
04-01 15:02:41.594: D/MyLinearLayout(1739): dispatchTouchEvent ACTION_DOWN
04-01 15:02:41.594: D/MyLinearLayout(1739): onInterceptTouchEvent ACTION_DOWN
04-01 15:02:41.594: D/MyRelativeLayout(1739): dispatchTouchEvent ACTION_DOWN
04-01 15:02:41.594: D/MyRelativeLayout(1739): onInterceptTouchEvent ACTION_DOWN
04-01 15:02:41.594: D/MyRelativeLayout(1739): onTouchEvent ACTION_DOWN
04-01 15:02:41.594: D/MyLinearLayout(1739): onTouchEvent ACTION_DOWN
04-01 15:02:41.594: D/Activity(1739): onTouchEvent ACTION_DOWN
04-01 15:02:41.714: D/Activity(1739): dispatchTouchEvent ACTION_UP
04-01 15:02:41.714: D/Activity(1739): onTouchEvent ACTION_UP
複製代碼
說明:RelativeLayout onInterceptTouchEvent 返回true,表示RelativeLayout 攔截事件信息,Button不會響應事件,事件交由RelativeLayout onTouchEvent處理。
ADS/ATS、LDS/LIS/LTS、RDT/RIT/RTF、BDF/BTF
複製代碼
日誌說明
04-01 15:27:17.002: D/Activity(1907): dispatchTouchEvent ACTION_DOWN
04-01 15:27:17.002: D/MyLinearLayout(1907): dispatchTouchEvent ACTION_DOWN
04-01 15:27:17.002: D/MyLinearLayout(1907): onInterceptTouchEvent ACTION_DOWN
04-01 15:27:17.002: D/MyRelativeLayout(1907): dispatchTouchEvent ACTION_DOWN
04-01 15:27:17.058: D/Activity(1907): dispatchTouchEvent ACTION_UP
04-01 15:27:17.058: D/MyLinearLayout(1907): dispatchTouchEvent ACTION_UP
04-01 15:27:17.058: D/MyLinearLayout(1907): onInterceptTouchEvent ACTION_UP
04-01 15:27:17.058: D/MyRelativeLayout(1907): dispatchTouchEvent ACTION_UP
複製代碼
說明:RelativeLayout dispatchTouchEvent return true 表示本身消費事件,再也不進行傳遞
ADS/ATS、LDS/LIS/LTS、RDF/RIT/RTF、BDF/BTF
複製代碼
日誌說明
04-01 15:32:12.138: D/Activity(1965): dispatchTouchEvent ACTION_DOWN
04-01 15:32:12.138: D/MyLinearLayout(1965): dispatchTouchEvent ACTION_DOWN
04-01 15:32:12.138: D/MyLinearLayout(1965): onInterceptTouchEvent ACTION_DOWN
04-01 15:32:12.138: D/MyRelativeLayout(1965): dispatchTouchEvent ACTION_DOWN
04-01 15:32:12.138: D/MyLinearLayout(1965): onTouchEvent ACTION_DOWN
04-01 15:32:12.138: D/Activity(1965): onTouchEvent ACTION_DOWN
04-01 15:32:12.250: D/Activity(1965): dispatchTouchEvent ACTION_UP
04-01 15:32:12.250: D/Activity(1965): onTouchEvent ACTION_UP
複製代碼
說明:RelativeLayout dispatchTouchEvent return false 表示不處理事件,交給上層頁面處理。
ADT/ATS、LDS/LIS/LTS、RDF/RIT/RTF、BDF/BTF
複製代碼
日誌說明
04-01 15:43:24.558: D/Activity(2023): dispatchTouchEvent ACTION_DOWN
04-01 15:43:24.686: D/Activity(2023): dispatchTouchEvent ACTION_UP
複製代碼
說明:同ViewGroup和View的 dispatchTouchEvent 方法同樣,return true 表示本身消費事件。不一樣的是,Activity 的dispatchTouchEvent方法return false 也表示本身消費事件。
ADS/ATS、LDS/LIS/LTS、RDF/RIT/RTF、BDF/BTF
複製代碼
日誌說明
04-01 15:56:51.486: D/Activity(2149): dispatchTouchEvent ACTION_DOWN
04-01 15:56:51.486: D/MyLinearLayout(2149): dispatchTouchEvent ACTION_DOWN
04-01 15:56:51.486: D/MyLinearLayout(2149): onInterceptTouchEvent ACTION_DOWN
04-01 15:56:51.486: D/MyRelativeLayout(2149): dispatchTouchEvent ACTION_DOWN
04-01 15:56:51.486: D/MyLinearLayout(2149): onTouchEvent ACTION_DOWN
04-01 15:56:51.486: D/Activity(2149): onTouchEvent ACTION_DOWN
04-01 15:56:51.490: D/Activity(2149): dispatchTouchEvent ACTION_UP
04-01 15:56:51.490: D/Activity(2149): onTouchEvent ACTION_UP
複製代碼
說明:其實,最終只要傳遞到Activity的onTouchEvent 方法,都會交由它處理事件。
參照以前理解的思路,將整個示意圖完善以下:
Activity
的dispatchTouchEvent
方法,執行父類dispatchTouchEvent
方法時,會將事件分發至ViewGroup
,不然自身消費事件。Activity
的onTouchEvent
方法,表示頁面中全部控件都不響應事件,由Activity
處理。ViewGroup
和View
的dispatchTouchEvent
方法,return true
表示不分發事件,自身處理。return false
就將事件傳遞給上層控件的onTouchEvent
方法,而且再也不響應上層控件傳遞過來的事件。ViewGroup
的onInterceptTouchEvent
方法return true
表示攔截事件,將事件傳遞給自身的onTouchEvent
方法處理。View
的onTouchEvent
方法return false
表示不消費事件,將事件傳遞給上層控件的onTouchEvent
方法。不然,消費事件。ViewGroup
的onTouchEvent
方法return true
表示消費事件,不然將事件傳遞給上層控件或Activity
的onTouchEvent
方法處理。最近在構建本身的博客主頁,正在將以前的博客遷移過去。有興趣請點擊Flueky Tech-site