Android 觸摸事件傳遞機(jī)制
1 觸摸事件的類型
- ACTION_DOWN : 用戶手指按下操作,一般標(biāo)志著觸摸事件的開始.
- ACTION_MOVE : 用戶按下后移動手指.
- ACTION_UP : 用戶手指離開屏幕.觸摸事件的結(jié)束.
一次屏幕的觸摸操作中,ACTION_UP 和 ACTION_DOWN 是必須有的.ACTION_MOVE視情況而定.
2. 事件傳遞的三個階段
-
事件分發(fā)(dispatch) : 事件的分發(fā)對應(yīng)著
dispatchTouchEvent
方法,在Android系統(tǒng)中所有的事件都是通過這個方法進(jìn)行分發(fā)的.函數(shù)原型 :
// 事件分發(fā)方法 public boolean dispatchTouchEvent(MotionEvent ev);
- 返回值
true
或false
: 當(dāng)前視圖將事件消耗,不再繼續(xù)分發(fā)給子視圖. - 返回值
super.dispatchTouchEvent(ev)
: 繼續(xù)分發(fā)事件.
- 返回值
-
事件攔截(Intercept) : 事件的攔截對應(yīng)著
onInterceptTouchEvent
方法.這個方法
只有在ViewGroup及其子類中才存在,View和Activity中不存在.函數(shù)原型 :
// 事件攔截 public boolean onInterceptTouchEvent(MotionEvent ev);
- 返回值
true
: 攔截此事件,不再繼續(xù)分發(fā).同時交給自身的onTouchEvent
方法進(jìn)行消費. - 返回值
false
或super.onInterceptTouchEvent
: 不攔截事件,繼續(xù)傳遞給子視圖.
- 返回值
-
事件消費(Consume) : 事件消費對應(yīng)著
onTouchEvent
方法.函數(shù)原型 :
// 消費函數(shù) public void onTouchEvent(MotionEvent ev);
- 返回值
true
: 當(dāng)前視圖可以處理當(dāng)前事件,事件將不會向上傳遞給父視圖. - 返回值
false
: 當(dāng)前視圖處理不了該事件,事件會被傳遞給父視圖的onTouchEvent
方法進(jìn)行處理.
- 返回值
3. Android擁有事件傳遞處理能力的類
-
Activity : 擁有
dispatchTouchEvent
和onTouchEvent
方法. -
ViewGroup :
dispatchTouchEvent
涮俄、onInterceptTouchEvent
和onTouchEvent
-
View : :
dispatchTouchEvent
归苍、onTouchEvent
4. View 的事件傳遞機(jī)制
參考代碼 : app , 下面對程序及結(jié)果進(jìn)行分析.
-
不進(jìn)行人為干預(yù). 不設(shè)置listener情況.
-
dispatchTouchEvent
和onTouchEvent
返回父類的同名方法. -
onTouch
返回false
運(yùn)行結(jié)果 :
MainActivity: dispatchTouchEvent : DOWN MyTextView: dispatchTouchEvent : DOWN MyTextView: onTouchEvent : DOWN MainActivity: onTouchEvent : DOWN MainActivity: dispatchTouchEvent : UP MainActivity: onTouchEvent : UP
從LOG中可以看出事件傳遞方式如下 :
-
dispatchTouchEvent
方法從外層向內(nèi)層傳遞. -
onTouchEvent
從內(nèi)層向外層傳遞. - 如果某一層處理了事,那么當(dāng)前事件序列的其他事件不會向下傳遞.對于當(dāng)前情況下由于MainActivity
處理ACTION_DOWN
事件 所以該事件序列中的ACTION_UP
事件也就到MainActivity就不
再下發(fā)給子視圖了.
-
-
不進(jìn)行人為干預(yù),設(shè)置listener情況.
onTouch返回false 運(yùn)行結(jié)果 :
MainActivity: dispatchTouchEvent : DOWN MyTextView: dispatchTouchEvent : DOWN MainActivity: onTouch : DOWN MyTextView: onTouchEvent : DOWN MainActivity: dispatchTouchEvent : UP MyTextView: dispatchTouchEvent : UP MainActivity: onTouch : UP MyTextView: onTouchEvent : UP MainActivity: MyTextView OnClick
onTouch返回true 運(yùn)行結(jié)果 :
// onTouch 返回true : the listener consume the event MainActivity: dispatchTouchEvent : DOWN MyTextView: dispatchTouchEvent : DOWN MainActivity: onTouch : DOWN MainActivity: dispatchTouchEvent : UP MyTextView: dispatchTouchEvent : UP MainActivity: onTouch : UP
LOG 信息顯示事件是 MyTextView 視圖處理的.
- 事件處理的流程
- 如果設(shè)置了listener則首先調(diào)用 listener 的
onTouch
方法.- 返回值
true
: 表示listener處理該事件.onTouchEvent
和onClick
不會被調(diào)用. - 返回值
false
: 表示listener不處理該事件.onTouchEvent
和OnClick
不會被調(diào)用.
- 返回值
-
onTouchEvent
如果onTouch
方法返回true
-
onClick
如果onTouch
方法返回true
- 如果設(shè)置了listener則首先調(diào)用 listener 的
- 事件處理的流程
-
dispatchTouchEvent
返回false
或true
在兩種情況下當(dāng)前視圖都會消耗該事件,該事件不會繼續(xù)分發(fā)給子視圖.
同時不會調(diào)用onTouchEvent
,onClick
等方法
MainActivity 運(yùn)行結(jié)果 :MainActivity: dispatchTouchEvent : DOWN MainActivity: dispatchTouchEvent : UP
MyTextView 運(yùn)行結(jié)果
MainActivity: dispatchTouchEvent : DOWN MyTextView: dispatchTouchEvent : DOWN MainActivity: dispatchTouchEvent : UP MyTextView: dispatchTouchEvent : UP
-
onTouchEvent
方法返回true
當(dāng)前視圖消耗該事件,該事件處理不會向上傳遞.
OnClick
方法不被調(diào)用MyTextView 運(yùn)行結(jié)果
MainActivity: dispatchTouchEvent : DOWN MyTextView: dispatchTouchEvent : DOWN MainActivity: onTouch : DOWN MyTextView: onTouchEvent : DOWN MainActivity: dispatchTouchEvent : UP MyTextView: dispatchTouchEvent : UP MainActivity: onTouch : UP MyTextView: onTouchEvent : UP
-
onTouchEvent
方法返回false
當(dāng)前視圖不處理該事件,事件將會被傳遞給上層控件處理.并且
onClick
不會被調(diào)用.MyTextView 運(yùn)行結(jié)果
MainActivity: dispatchTouchEvent : DOWN MyTextView: dispatchTouchEvent : DOWN MainActivity: onTouch : DOWN MyTextView: onTouchEvent : DOWN MainActivity: onTouchEvent : DOWN MainActivity: dispatchTouchEvent : UP MainActivity: onTouchEvent : UP
-
onTouchEvent
返回super.onTouchEvent(ev)
MyTextView 運(yùn)行結(jié)果 :
MainActivity: dispatchTouchEvent : DOWN MyTextView: dispatchTouchEvent : DOWN MainActivity: onTouch : DOWN MyTextView: onTouchEvent : DOWN MainActivity: dispatchTouchEvent : UP MyTextView: dispatchTouchEvent : UP MainActivity: onTouch : UP MyTextView: onTouchEvent : UP MainActivity: MyTextView OnClick
5. ViewGroup 事件傳遞
-
onIntercepTouchEvent
返回false
或super.onIntercepTouchEvent
在這種情況下,事件會繼續(xù)分發(fā).
MyRelativeLayout 運(yùn)行結(jié)果 :
MainActivity: dispatchTouchEvent : DOWN MyRelativeLayout: dispatchTouchEvent : DOWN MyRelativeLayout: onInterceptTouchEvent : DOWN MyTextView: dispatchTouchEvent : DOWN MainActivity: onTouch : DOWN MyTextView: onTouchEvent : DOWN MainActivity: dispatchTouchEvent : UP MyRelativeLayout: dispatchTouchEvent : UP MyRelativeLayout: onInterceptTouchEvent : UP MyTextView: dispatchTouchEvent : UP MainActivity: onTouch : UP MyTextView: onTouchEvent : UP MainActivity: MyTextView OnClick
-
onInterceptTouchEvent
返回true
在這種情況下,此視圖會攔截事件,并交給自身的
onTouchEvent
處理.
MyRelativeLayout 運(yùn)行結(jié)果 :// 事件最終是Activity處理的. MainActivity: dispatchTouchEvent : DOWN MyRelativeLayout: dispatchTouchEvent : DOWN MyRelativeLayout: onInterceptTouchEvent : DOWN MyRelativeLayout: onTouchEvent : DOWN MainActivity: onTouchEvent : DOWN MainActivity: dispatchTouchEvent : UP MainActivity: onTouchEvent : UP