在Android的觸摸點擊等事件中我們經常需要用到時間分發機制,看了很多朋友寫的博客,感覺不是很明朗,綜合多家的精粹用通俗的描述全面的介紹下事件分發機制。
1。首先來一張全局圖
1代表我們的activity
2代表我們的viewgroup 也就是我們經常說的容器
3 就是最頂層的view了 比偶如說 textview imageview等
先簡單的介紹下,稍後再代碼分析
當點擊最頂層的view的時候
down事件經過: activity的分發機制函數 dispatchTouchEvent 當返回true或者false的時候事件就在分發中就會被消費,不會傳到上一層,也不會執行activity的 onTouchEvent
/**
* 事件的分發
* 分發事件的方法。當接收到事件時,通過調用此方法來決定是否分發。
* @param ev
* @return
* true: 事件不再進行分發且已經在自身事件的分發中被消費
* false: 也不對事件進行分發。
* 也就是說該方法不論是返回true還是返回false都不會對事件進行分發,
*
* 只有當返回系統默認super.dispatchTouchEvent(ev)時,纔會將事件分發給本層
* 的攔截事件onInterceptTouchEvent(MotionEvent ev)去處理,如果沒有onInterceptTouchEvent(MotionEvent ev)方法
* 則直接分發給子View中的onInterceptTouchEvent(MotionEvent ev)方法處理
*
*/
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if(ev.getAction() == MotionEvent.ACTION_DOWN){
Log.d("data","[LinearLayout]--dispatchTouchEvent:"+ev.getAction()+" "+super.dispatchTouchEvent(ev));
}
return super.dispatchTouchEvent(ev);
}
/*log日誌
*EventActivity: dispatchTouchEvent=====ACTION_DOWN
*EventActivity: dispatchTouchEvent=====ACTION_UP
*/
activity的 dispatchTouchEvent返回super.dispatchTouchEvent(ev)的時候事件往下傳遞進入viewgroup的分發機制中,
如果viewgroup的 dispatchTouchEvent返回true/false的時候,事件不會被往下分發,而是回傳到activity的onTouchEvent去消費事件,在activity中的onTouchEvent執行完事件後如果返回true表示消費了這個事件,傳遞到此結束,返回false表示不處理事件,繼續分發,此時事件就丟失了
如果viewgroup的 dispatchTouchEvent返回super.dispatchTouchEvent(ev);的時候,down事件就會繼續繼續向上傳遞,到達View頂層的dispatchTouchEvent,如果View的dispatchTouchEvent返回true/false的時候,事件會傳遞給viewgroup的onTouchEvent去消費事件,只有返回super.dispatchTouchEvent(ev);纔會調用本層的onTouchEvent,如果本層onTouchEvent返回true,事件到此結束,相當於消耗了事件。如果返回false的話,接下來的move和up事件將不會分配給View,而是直接在viewgroup的onTouchEvent去消費事件。
ViewGroup特有的時間攔截 onInterceptTouchEvent
/**
* 事件的攔截
* 攔截事件方法,該方法只有在佈局或者ViewGroup中纔會有。通過調用該方法來決定是否對事件
* 進行攔截。
* @param ev
* @return
* true:進行攔截,將事件進行分發onTouchEvent方法處理
* false:不對事件進行攔截,傳遞給下一級處理
*/
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if(ev.getAction() ==MotionEvent.ACTION_DOWN){
Log.d("data","[LinearLayout]--onInterceptTouchEvent:"+ev.getAction()+" "+super.onInterceptTouchEvent(ev));
}
return super.onInterceptTouchEvent(ev);
}
事件處理函數
/**
* 事件的處理
* 處理事件。當對事件進行了攔截時,將會調用onTouchEvent方法對事件進行處理。
*
* @param ev
* @return
* true:表示該View能處理該事件,事件將終止向上傳遞(傳遞給其父View)
* false:不能處理,則把事件傳遞給其父View的onTouchEvent方法來處理
*/
@Override
public boolean onTouchEvent(MotionEvent ev) {
if(ev.getAction() ==MotionEvent.ACTION_DOWN){
Log.d("data","[LinearLayout]--onTouchEvent:"+ev.getAction()+" "+super.onTouchEvent(ev));
}
return super.onTouchEvent(ev);
}
//注意:onTouchEvent事件消費函數一旦返回false 後面的鼠標UP 和 MOVE 就不會在這裏執行了,但是下一次down事件能獲取到
Android中的事件在表現形式上有很多,如onTouch、onClick和onLongClick等,在具體微觀上的表現形式有action_down、action_move和action_up等。但是不管是哪種表現形式,都是基於事件的傳遞。