當用戶點擊屏幕時,將產生的觸摸事件分爲以下四種
ACTION_DOWN剛剛觸摸屏幕
ACTION_MOVE 手指在屏幕滑動
ACTION_UP:手指離開屏幕
ACTION_CANCEL 非人爲因素的取消
事件分發的對象有
Activity:控件的生命週期和處理事件
ViewGroup: 一組View的集合
View所有UI組件的基類
主要涉及到的方法
dispahchTouchEvent 用來事件分發
onIntercepterTouchEvent 判斷事件是否攔截(這個只有ViewGroup裏有)
onTouchEvent處理點擊事件
當一個事件發和的時候是由Activity來分發的 所以走的是Activity的dispatchTouchEvent方法,而整個屏幕又是一個PhoneWindow,也就是由PhoneWindow來分發的,PhoneWindow裏面則由窗口頂層佈局DecorView來執行,DecorView是一個FragLayout子類,所以最終來還走到ViewGroup的dispatchTouchEvent, 如果Activity裏的dispatchTouchEvent返回false,就會調用Activity.onTouchEvent方法,onTouchEvent這個方法會對觸摸邊界進行判斷,返回true則是這個界面銷燬了,false則是這個事件消費了,到此結束.
上面小結一下: 如果一個觸摸事件沒有任何View消費的話,最後就是走到Activity.onTouchEvent中
ViewGroup dispathTouchEvent()
一個事件的開始是由ACTION_DOWN開始的,在這裏會做一系列初始化,在ACTION_DOWN的時候,裏面有個標記
FLAG_DISALLOW_INTERCEPT 的判斷,而這個值會由requestDisallowInterceptTouchEvent來賦值,這個值會直接影響到是否會將走到onInceptetTouchEvent裏面,但這個值不會影響ACTION_DOWN事件,只會影響其以外的觸摸事件.
如果一切正常,說會走到onInterceptTouchEvent這個事件攔截裏面,默認返回的是false,爲不攔截.
再如果onInterceptTouchEvent返回false的話,則在ACTION_DOWN觸摸事件裏會倒序遍歷整個子View,裏面檢測View是否可見,是否在執行動畫,是否在這個View的範圍內.遍歷完後,如果還是沒有發再這個View,,則最終走的就是ViewGroup的父類的dispathcTouchEvent方法中,也就是VIew的dispatchTouchEvent,然後就是onTouchEvent方法
如果找到了這個View,就會處理其它的觸摸事件,比如MOVE,UP等,就會走到子View的dispatchTouchEvent
View.onTouchEvent
在View的dispatchTouchEvent方法中,如果我們設置了touchEventListener的話就會爲一個ListenerInfo附值,不爲空,則先執行onTouch方法,如果onTouch方法返回true,則代碼這個事件被消費,沒有下一步,如果返回false或都沒有setOnTouchListener的話纔會到onTouchEvent(...)方法裏
這裏面主要是對長按和點擊事件做處理,時面有個500ms的延時任務,如果在up的時候超過500則是長按,長按事件如果返回true則onClick不響應,如果小於500則反之,將長按flag設置爲fase 並移除了長按事件,.就會響應onClick點擊事件,當然需要setOnclickListener
如果設置了長按事件並返回了true則不會執行點擊事件,如果長按事件返回fase則點擊事件也會執行.
總結: 點擊事件觸發--->根View的ViewGroup-->調用dispatchTouchEvent-->調用onInterceptTouchEvent-->
是否攔截 是-->調用自己的onTouchEvent-->是否消費 --- 否--->Activity onTouchEvent結束
--- 是--->事件消費結束
否-->子ViewGroup-->調用dispatchTouchEvent-->調用onInterceptTouchEvent-->是否攔截 是:調用自己的onTouchEvent
否:View-->調用View的dispatchTouchEvent--->View沒有onInterceptTouchEvent方法直接到--->自己的onTouchEvent