在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等。但是不管是哪種表現形式,都是基于事件的傳遞。