View事件分發機制,view事件分發
所謂的事件分發,其實就是對MotionEvent事件的分發過程,即當一個MotionEvent產生後,系統需要把這個事件傳遞給一個具體的View,而這個傳遞的過程就是分發過程。
點擊事件的分發由3個方法共同完成:
public boolean dispatchTouchEvent(MotionEvent event)
用來進行事件分發,如果事件能傳遞給當前View,那麼此方法一定會被調用,返回結果受View的onTouchEvent 和下級的dispatchTouchEvent方法影響,表示是否消耗當前事件。
public boolean onInterceptTouchEvent(MotionEvent ev)
在上述方法內部調用,用來判斷是否攔截是否攔截某個事件,如果當前View攔截了某個事件,那麼在同一個事件序列中,此方法不會再次調用,返回結果表示是否攔截當前事件
public boolean onTouchEvent(MotionEvent event)
在dispatchTouchEvent 方法中調用,用來處理點擊事件,返回結果是否消耗當前事件,如果不消耗,則在同一個事件序列中,當前View無法再次接受到事件。
對於一個根ViewGroup來說:
產生事件後
首先傳遞它,這時dispatchTouchEvent 會調用ViewGroup的onInterceptTouchEvent
-----ViewGroup的onInterceptTouchEvent返回true就表示攔截當前事件,接著事件會交給ViewGroup處理,即onTouchEvent會被調用
-----ViewGroup的onInterceptTouchEvent返回false表示不攔截事件,這個事件會傳遞給子項目,接著子項目的dispatchTouchEvent會被調用
事件傳遞:activity > Window > view
事件傳遞結論:
1.同一個事件序列是從手指接觸螢幕那一刻開始,到手指離開螢幕那一刻結束。
2.正常情況下,一個事件序列只能被一個View攔截且消耗
3.某個View一旦決定攔截,那麼這個事件序列只能它來處理,它的onInterceptTouchEvent不會再被調用 4.某個View一旦開始,如果它不消耗ACTION_DOWN 事件即onTouchEvent返回來false,那麼同一事件序列中的其它事件都不會再交給它來處理。
5.如果不消耗ACTION_DOWN以外的事件,那麼這個點擊事件會消失,此時父元素的onTouchEvent並不會被調用,並且當前View回持續收到後續事件,最後這些消失的事件會傳遞個給Activity處理
6.ViewGroup預設不攔截事件onInterceptTouchEvent預設返回fakse
7.View 沒有onInterceptTouchEvent,一旦事件傳遞給View,onTouchEvent就會被調用
8.View的onTouchEvent預設消耗事件,返回true,除非它不可點擊 clickable和longClickable同時為false;View的longClickable預設未false,clickable要分情況;
9.View的enable屬性不影響onTouchEvent的預設值返回。
10.onClick 會發生的前提是當前View是可點的,並收到down 和up 事件
11.事件傳遞過程是由外向內的,事件總是先傳遞給父元素再由父元素分發給子項目。