標籤:android事件 event strong com src -- 一個 證明 one
ViewGroup 分發-> 攔截 -> 處理
在事件分發的過程中,主要涉及到三個方法:
分發處理流程:
1、在dispatchTouchEvent中,先調用ViewGroup自身的onInterceptTouchEvent方法,判斷自己是否要攔截。
2、如果這時候自己攔截,那就調用自己的onTouchEvent方法,如果onTouchEvent方法返回了True,那麼這次的事件就算消耗了,事件傳遞到此為止,,如果返回了False,證明這次沒有消耗這次MotionEvent,那麼這次的事件就會往上返回,由上一級繼續處理。
3、如果當前ViewGroup的onInterceptTouchEvent返回了False,那就會調用它的子view的dispatchTouchEvent方法,這樣這個事件就傳遞下去了,如果它的子View處理不了,那麼還會回來調用ViewGroup的onTouchEvent方法。
View
View不同於ViewGroup的是,View中沒有onInterceptTouchEvent方法,因為View作為事件處理的最後一級,不需要判斷是否要攔截,是一定要攔截,不管能不能處理,都要試一下,所以在View中調用流程是:dispatchTouchEvent -> onTouchEvent
注意:
view的enable狀態和onTouchEvent是沒有關係的,只有clickable狀態是對onTouchEvent有影響的。
設定 view的enable為false確實也會把view的clickable設成false,但是設定view的onclickListener就又把view的clickable變成了true,所以最後的解決方案就是把那兩行代碼換下先後順序,問題就迎刃而解了。
GesutureDetector處理事件
GestureDetector是一個手勢輔助檢測類,預設能夠檢測多種手勢:
onTouchListener OnTouchEvent OnClickListener
我們在知道onTouchEvent之前肯定都知道onClickListener和onTouchListener,而他們都是事件的消費者,onTouchListener是在onTouch方法中生效,而且onTouch要先於onTouchEvent,就是說一旦設定了onTouchListener並且最後onTouch方法返回了True,那onTouchEvent將不會再被執行,而onClickListener和onTouchEvent有些關係,onTouchEvent的預設實現裡會調用onClickListener的onClick方法,如果重寫了onTouchEvent,因為onClickListener接受不到ACTION_DOWN和ACTION_UP,那麼再設定onClickListener也就不會再生效了,這個時候的單擊或者長按處理只能在onTouchEvent中自己處理。
結論:
1、如果事件不被攔截,整個事件傳遞流向將呈U型狀態。
Activity---->ViewGroup--->View 從上往下調用dispatchTouchEvent方法,一直到葉子節點(View)的時候,再由View--->ViewGroup--->Activity從下往上調用onTouchEvent方法。
2、dispatchTouchEvent 和 onTouchEvent 一旦return true,事件就停止傳遞了(到達終點)
3、dispatchTouchEvent 和 onTouchEvent return false的時候事件都回傳給父控制項的onTouchEvent處理。
4、dispatchTouchEvent、onTouchEvent、onInterceptTouchEvent
ViewGroup 和View的這些方法的預設實現就是會讓整個事件安裝U型完整走完,所以 return super.xxxxxx() 就會讓事件依照U型的方向的完整走完整個事件流動路徑),中間不做任何改動,不回溯、不終止,每個環節都走到。
總結:
- 對於 dispatchTouchEvent,onTouchEvent,return true是終結事件傳遞。return false 是回溯到父View的onTouchEvent方法。
- ViewGroup 想把自己分發給自己的onTouchEvent,需要攔截器onInterceptTouchEvent方法return true 把事件攔截下來。
- ViewGroup 的攔截器onInterceptTouchEvent 預設是不攔截的,所以return super.onInterceptTouchEvent()=return false;
- View 沒有攔截器,為了讓View可以把事件分發給自己的onTouchEvent,View的dispatchTouchEvent預設實現(super)就是把事件分發給自己的onTouchEvent。
對於ACTION_MOVE、ACTION_UP總結:ACTION_DOWN事件在哪個控制項消費了(return true), 那麼ACTION_MOVE和ACTION_UP就會從上往下(通過dispatchTouchEvent)做事件分發往下傳,就只會傳到這個控制項,不會繼續往下傳,如果ACTION_DOWN事件是在dispatchTouchEvent消費,那麼事件到此為止停止傳遞,如果ACTION_DOWN事件是在onTouchEvent消費的,那麼會把ACTION_MOVE或ACTION_UP事件傳給該控制項的onTouchEvent處理並結束傳遞。
Android事件分發