View的兩個方法dispatchTouchEvent和onTouchEventhtml
探索andorid的事情傳遞以前應該知道android有兩個基礎的空間,view和viewGroup。view就是普通的控件,如button,Textview繼承自view,是沒有子佈局的。viewgroup表示能夠有子控件,如linearlayout,listview。android
事件即MotionEvent,主要有3中ide
(1)MotionEvent.ACTION_DOWN 按下View,是全部事件的開始函數
(2)MotionEvent.ACTION_MOVE 滑動事件佈局
(3)MotionEvent.ACTION_UP 與down對應,表示擡起ui
事件傳遞機制的目的是爲觸發view方法的點擊監聽和觸摸的監聽:spa
view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { } }); }
view.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { return false; } });
onTouch監聽裏面的這個return false有大學問,下面就來研究下這個返回.net
view的事件傳遞有兩個函數,dispatchTouchEvent負責分發事件,在dispatch***裏又會調用onTouchEvent表示執行事件,或者說消費事件。事件傳遞的入口是View的dispatchTouchEvent()函數:orm
dispatchTouchEvent是觸摸事件的分發的,事件多數是從activity的dispatchTouchEvent開始執行super.htm
dispatchTouchEvent(ev),事件向下分發。
oninterceptTouchevent是viewgroup提供的方法,默認返回false,返回true表示攔截
onTouchEvent是view提供的方法,view中默認返回true,表示消費了此事件
View裏,有兩個回調函數 :
ViewGroup裏,有三個回調函數 :
在Activity裏,有兩個回調函數 :
android中默認的狀況下是傳遞到view,傳遞過程是從父佈局到子佈局,也就是從acitivity到viewGroup到view的過程,
Android中事件傳遞過程(按箭頭方向)以下圖,圖片來自[qiushuiqifei],謝謝[qiushuiqifei]整理。
觸摸事件是一連串ACTION_DOWN,ACTION_MOVE..MOVE…MOVE、最後ACTION_UP,觸摸事件還有ACTION_CANCEL事件。事件都是從ACTION_DOWN開始的,Activity的dispatchTouchEvent()首先接收到ACTION_DOWN,執行super.dispatchTouchEvent(ev),事件向下分發。
dispatchTouchEvent()返回true,後續事件(ACTION_MOVE、ACTION_UP)會再傳遞,若是返回false,dispatchTouchEvent()就接收不到ACTION_UP、ACTION_MOVE。
下面的幾張圖參考自[eoe]
圖1.ACTION_DOWN都沒被消費
圖2-1.ACTION_DOWN被View消費了
圖2-2.後續ACTION_MOVE和UP在不被攔截的狀況下都會去找VIEW
圖3.後續的被攔截了
圖4ACTION_DOWN一開始就被攔截
android中的Touch事件都是從ACTION_DOWN開始的:
單手指操做:ACTION_DOWN---ACTION_MOVE----ACTION_UP
多手指操做:ACTION_DOWN---ACTION_POINTER_DOWN---ACTION_MOVE--ACTION_POINTER_UP---ACTION_UP.
在ontouchevent中有一個performClick()裏面調用了onclick方法
1.也就是說點擊某個事件的時候會先執行dispatch***而後3個判斷都對上會執行ontouchEvent,若是一切順利,onTouchEvent會調用onclick方法
2.不管ondispatch**返回true或者ontouch返回true。事件都會被消費,不會再往下傳了。若是dispatch***在執行onTouch監聽的時候,onTouchEvent返回了true,那麼它也返回true,這個事件提早被onTouch消費掉了。就再也不執行onTouchEvent了,更別說onClick監聽了。
onTouch是個監聽方法,默認返回的是false,若是爲true,就表示事件消費,就不會去執行OnTouchEvent方法了
總結,會先執行父佈局的dispathc**方法。子佈局中dispathc*方法。而後看子佈局中的ontouch方法的返回類型,若是爲false。證實時間沒有被消費,就會執行子佈局的ontouchevent方法,在執行父佈局的ontouchevent方法。ontouch方法默認返回false,就證實touchenvent方法會被執行,若是不想讓他執行的話,就返回true,這樣ontouchEvent方法就不會執行 。最後纔會執行onclick方法。