Android事件分發的詳解

當用戶點擊屏幕時,將產生的觸摸事件分爲以下四種

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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章