1. 程式人生 > >Touch事件傳遞機制解析

Touch事件傳遞機制解析

涉及的知識點:

主要涉及的方法:

方法 用途
public boolean dispatchTouchEvent(MotionEvent ev) 用來分發TouchEvent
public boolean onInterceptTouchEvent(MotionEvent ev) 用來攔截TouchEvent
public boolean onTouchEvent(MotionEvent ev) 用來處理TouchEvent

擁有這三個方法的類:

型別 相關類 方法
Activity類 Activity dispatchTouchEvent(); onTouchEvent();
View容器(ViewGroup的子類) FrameLayout、LinearLayou、ListView、ScrollVIew… dispatchTouchEvent(); onInterceptTouchEvent(); onTouchEvent();
View控制元件(非ViewGroup子類) Button、TextView、EditText…… dispatchTouchEvent(); onTouchEvent();

ViewGroup的dispatchTouchEvent是真正在執行“分發”工作,而View的dispatchTouchEvent方法,並不執行分發工作,或者說它分發的物件就是自己,決定是否把touch事件交給自己處理,而處理的方法,便是onTouchEvent事件

三個方法的具體作用:

方法 用途
dispatchTouchEvent() 用來分派事件。其中呼叫了onInterceptTouchEvent()和onTouchEvent(),一般不重寫該方法
onInterceptTouchEvent() 用來攔截事件。ViewGroup預設為(return false)表示不對事件進行攔截,事件將向下傳遞(傳遞給其子View);若手動重寫該方法,使其返回true則表示攔截,事件將終止向下傳遞,則事件將由當前ViewGroup類(onTouchEvent)來處理
onTouchEvent() 用來處理事件。返回true則表示該View能處理該事件,事件將終止向上傳遞(傳遞給其父View);返回false表示不能處理,則把事件傳遞給其父View的onTouchEvent()方法來處理

三個方法並不總是同時存在的

無攔截的touch事件處理過程

流程圖

(檢視巢狀關係 Activity–>out–>middle–>center,點選center)
這裡寫圖片描述

分析

分發過程中,所有元件都不會處理事件,且事件並不會被center的onTouchEvent方法“消費”(ruturn false),則事件會層層逆向傳遞迴到Activity。對於後續的move、up事件,由於第一個down事件已經確定由Activity處理事件,故up事件由Activity的dispatchTouchEvent直接分發給自己的onTouchEvent方法處理。
即,onInterceptTouchEvent()來決定是否將事件傳遞給子View處理,onTouchEvent()用來對具體事件的處理(對一些功能的實現)並且決定了是否將處理事件的能力返回給父View.

例項分析

一次點選(擡起)操作,當前的activity分別會響應一次ActionDown,n次ActionMove(n>=0),1次ActionUp事件

Demo示圖

例. 檢視巢狀 Activity–>ViewA–>ViewB–>ViewC(其中ViewA、ViewB繼承至FrameLayout,ViewC繼承自View)
這裡寫圖片描述

情況一(點選ViewC,過程中無任何攔截)

(注:logout中的Main表示Activity)

這裡寫圖片描述

情況二(點選ViewC,過程中存在攔截操作)

點選ViewC, 只在ViewA中對事件下發過程進行攔截onInterceptTouchEvent{…..return true;},並且ViewA中的onTouchEvent不處理事件(return false),事件回傳
這裡寫圖片描述

情況三(點選ViewB, 對事件回傳過程進行截獲)

只在ViewA中對事件回傳過程進行截獲onTouchEvent{…..return true;}

這裡寫圖片描述
(ActionDown結束後,後續的事件(Move、Up)傳遞過程中,只有被確定處理該touch事件的view才進行onTouchEvent方法的響應)
說明:一次完整的Touch事件,應該是由一個Down、一個Up和若干個Move組成的。Down方式通過dispatchTouchEvent分發,分發的目的是為了找到真正需要處理完整Touch請求的View。當某個View或者ViewGroup的onTouchEvent事件返回true時,便表示它是真正要處理這次請求的View,之後的Aciton_UP和Action_MOVE將由它處理。當所有子View的onTouchEvent都返回false時,這次的Touch請求就由根ViewGroup,即Activity自己處理了。

情況四(點選ViewC, 對事件分發過程進行攔截):

在ViewB中對事件分發過程進行攔截dispatchTouchEvent{…..return true;}

這裡寫圖片描述