觸摸事件分發:就是一個為了解決觸摸事件沖突而設置的機制
1.事件類型
ACTION_DOWN -> ACTION_UP / ACTION_CANCEL
ACTION_DOWN -> ACTION_MOVE -> ACTION_MOVE -> ACTION_MOVE -> ACTION_UP / ACTION_CANCEL
這個取消事件ACTION_CANCEL它是一種特殊的事件,它對應的是時間序列的非人為的提前結束
2.onTouchEvent()
在Android里面,每一個觸摸事件都會交給View的onTouchEvent()方法來處理
當用戶的手指剛剛觸摸到屏幕的時候,也就是一個事件組第一個事件DOWN發生的時候,Android會從用戶的觸摸點上離用戶最近的那個View開始,向下一個一個地去調用每一個View的onTouchEvent(),如果View的onTouchEvent()對這個Down事件沒有響應,它就會繼續向下,直到遇到第一個做出響應的View,這個向下的過程才會結束。這個時候,這個View就成為了這組事件的接收者,這個DOWN事件的后續事件都會直接發送給它,不會給它上面的View,也不會給它下面的View,直到這組事件結束,也就是UP事件或者CANCEL事件出現
View是否響應DOWN事件,其實取決于onTouchEvent()的返回值是否為true。其實只有DOWN事件的返回值需要是true,像后續事件UP或者MOVE它們的返回值是沒有影響的。但是如果要自定義,全都寫成true不是挺方便的嗎
如果想要寫自己的觸摸反饋算法,只要重寫onTouchEvent()在里面寫自己的算法,然后返回true就好了
3.onInterceptTouchEvent()
它用于觸摸事件分發里面的事件攔截機制
在用戶觸摸屏幕的時候,每一個觸摸事件到達View的onTouchView()之前,Android會從整個Activity里面最底部的那個根View,向上一級一級地詢問:你要不要攔截這組事件,如果整個流程走完,所有的ViewGroup都不攔截,這個時候就會走第二個流程:onTouchEvent() 從上往下。而如果中途某個View攔截事件,那么這個事件就不會再發給它的子View,而是直接轉交給它自己的onTouchEvent()來處理,并且在這之后的這個事件組的所有后續事件就全部都會被自動攔截了,不會再交給它的子View,也不會交給它的onInterceptTouchEvent(),而是直接交給它的onTouchEvent()
ViewGroup是否攔截事件,是通過調用 ViewGroup 的 onInterceptTouchEvent() 方法來實現的,返回true表示攔截
當onInterceptTouchEvent()返回true的時候,除了完成事件接管,它還會對它的子View發送一個額外的取消事件CANCEL,通知子View恢復狀態
另外onInterceptTouchEvent()和onTouchEvent()有一點不同在于,onTouchEvent()是否要消費這組事件是需要在DOWN事件中決定的,如果在DOWN事件發過來的時候返回了false,那么以后你就跟這組事件無緣了,沒有第二次機會;而onInterceptTouchEvent()則是你在整個過程中都可以對事件流中的每個事件進行監聽,隨時可以返回true,來對事件流進行接管。
所以如果要寫一個可以滑動或者捏撐的ViewGroup,那么除了重寫onTouchEvent()來處理事件,還需要重寫onInterceptTouchEvent(),在DOWN事件的時候返回false,然后在后續事件中,在你覺得合適的時候,返回true來實現事件的攔截接管
4.requestDisallowInterceptTouchEvent()
在事件過程中在子View里面,調用父View的requestDisallowInterceptTouchEvent(true),例如getParent().requestDisallowInterceptTouchEvent(true),父View在這個事件流中就不會再通過onInterceptTouchEvent()來嘗試攔截了,并且它是一個遞歸方法,它會阻止每一級父View的攔截,不過僅限于當前事件流
5.dispatchTouchEvent()
它是事件分發的總的調度方法,onTouchEvent() 和 onInterceptTouchEvent() 其實都是在dispatchTouchEvent()里面發生的,一個事件分發的過程,實質上就是從根View遞歸地調用了一次dispatchTouchEvent() 的過程
參考文章:
HenCoder 自定義 View 3-1 觸摸反饋,以及 HenCoder Plus