国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

View的事件分發機制

2019-11-09 16:46:17
字體:
來源:轉載
供稿:網友

  View負責android應用的顯示,有很重要的地位,而理解View的事件分發機制是實現高質量自定義View和解決滑動沖突問題的基礎,既是重點,也是難點。   本文首先介紹View事件分發機制的流程,然后總結出View事件分發機制的一些結論,最后分析源碼知道這些結論是怎么總結來的。


流程

  所謂點擊事件的事件分發,其實就是對MotionEvent事件的分發過程。當手指點擊屏幕時,就會產生一個MotionEvent,然后系統需要把這個事件傳遞給一個具體的View,這個傳遞的過程,就是事件分發。   事件分發流程:   首先,系統會將事件分發給Activity的dispatchTouchEvent(ev)方法,在dispatchTouchEvent(ev)方法中,默認實現下,Activity會把事件分發給Window,Window再把事件分發給DectorView,DectorView接著把事件分發給頂層View,頂層View接著把事件分發給各級子View。如果有View消費了事件,dispatchTouchEvent(ev)會返回true并返回,表示已消費了事件。如果沒有View消費事件,dispatchTouchEvent(ev)方法會把事件傳遞給Activity的onTouchEvent(ev)方法。如果重寫dispatchTouchEvent(ev)方法并返回true或false,事件就不再傳遞給Window及各級View,而直接在Activity的dispatchTouchEvent(ev)中消費。   如果事件傳遞給了ViewGroup,就會調用它的dispatchTouchEvent(ev)方法。默認實現下,它會詢問自身的onInterceptTouchEvent(ev)方法是否攔截事件。如果攔截,首先,它會查看是否設置有touchListener,如果設置有,就調用onTouch(ev)方法,如果onTouch(ev)方法返回true,表示已消費事件,它就返回true,表示事件已在本ViewGroup消費,如果onTouch(ev)方法返回false,它就調用自身的onTouchEvent(ev)方法消費事件。如果不攔截,它就把事件傳遞給子View的dispatchTouchEvent(ev)方法。如果重寫dispatchTouchEvent(ev)并返回true,表示直接在這個方法中消費事件,事件不再傳遞。如果重寫并返回false,表示不在本View及子View中消費事件,事件會返回給上級,一般情況下,上級會在dispatchTouchEvent(ev)方法中把事件傳遞給onTouchEvent(ev)處理。   如果事件傳遞給了View,就會調用它的dispatchTouchEvent(ev)方法。默認情況下,它會查看是否設置有touchListener,如果設置有,就調用onTouch(ev)方法,之后與ViewGroup相同,如果onTouch(ev)返回true,就不調用onTouchEvent,如果返回false,就調用。如果重寫dispatchTouchEvent(ev)并返回true,表示直接在這個方法中消費事件,事件不再傳遞。如果重寫并返回false,表示不在本View中消費事件,事件會返回給上級,一般情況下,上級會在dispatchTouchEvent(ev)方法中把事件傳遞給onTouchEvent(ev)處理。   當事件傳遞給View或ViewGroup的onTouchEvent時,如果返回true,表示事件在這里消費,事件停止傳遞,如果返回false或super,表示事件不在這里消費,事件會被返回給上級處理。super中的默認實現會在ACTION_UP事件發生時會調用performClick,在這個方法中會檢查是否設置有點擊事件監聽器,如果設置有,就會調用onClick事件。   事件分發流程圖如下: View事件分發流程圖


結論

1 Activity的onTouchEvent默認實現返回false。View中onTouchEvent默認實現返回true,ViewGroup中onTouchEvent繼承自View。默認返回true表明事件默認會在最子層View上消費。2 在View和ViewGroup中,優先級onTouchListener > onTouchEvent > onClick。dispatchTouchEvent先檢查是否設置有onTouchListener,如果設置有,就調用onTouch。如果onTouch返回false,才調用onTouchEvent。在onTouchEvent中在ACTION_UP時,調用performClick方法檢查是否設置有onClickListener,如果有,就調用onClick方法。3 onClick會發生的前提是,onTouchEvent被調用,且調用了默認實現,且收到了UP事件,且view是可點擊的(clickable & ebabled)。4 View的onTouchEvent默認都會消耗事件(返回true),除非它是不可點擊的(clickable和longclickable同時為false)。View的longClickable屬性默認為false,clickable屬性要分情況,如Button的clickable屬性默認為true,而TextView的clickable屬性默認為false。View的enable屬性不影響onTouchEvent的默認返回值。哪怕一個View是disable狀態的,只要它的clickable或者longClickable有一個為true,那么它的onTouchEvent就返回true。5 ACTION_DOWN事件的傳遞如上圖所示。ACTION_DOWN事件在哪個控件消費了(return true), 那么ACTION_MOVE和ACTION_UP就會從上往下(通過dispatchTouchEvent)做事件分發往下傳,就只會傳到這個控件,不會繼續往下傳,如果ACTION_DOWN事件是在dispatchTouchEvent消費,那么事件到此為止停止傳遞,如果ACTION_DOWN事件是在onTouchEvent消費的,那么會把ACTION_MOVE或ACTION_UP事件傳給該控件的onTouchEvent處理并結束傳遞。如下圖所示。 MOVE和UP事件傳遞1

MOVE和UP事件傳遞2

MOVE和UP事件傳遞3

6 public boolean dispatchTouchEvent(MotionEvent ev); 如果事件傳遞到該view,那么此方法一定會被調用。返回結果受當前view的onTouchEvent和下級view的dispatchTouchEvent影響,表示是否消耗當前事件。重寫并返回true,表示事件在此方法消費,不再傳遞。重寫并返回false,表示事件不在此view及子view消費,事件會被上級處理。默認實現在Activity、ViewGroup、View中各不相同。7 ViewGroup的dispatchTouchEvent的默認實現中,首先會判斷如果當前在DOWN事件,就重置DISALOW_INTERCEPT_FLAG,保證DOWN事件時,dispatchTouchEvent一定會調用onInterceptTouchEvent。然后判斷是否攔截事件,如果是DOWN事件或DOWN事件已在子View中消費,就判斷是否允許調用onInterceptTouchEvent,如果不允許,表示不能攔截事件。如果不是DOWN事件,且沒有子View消費了事件,就直接攔截事件,且不再調用onInterceptTouchEvent方法。Flag在requestDisallowIntercept方法中重置,該方法在子view中調用。該方法生效的前提是ViewGroup的onInterceptTouchEvent中沒有攔截DOWN事件而攔截了MOVE和UP事件,因為如果攔截了DOWN事件,子view就不會再接收到任何事件,而不攔截DOWN事件,在子view中就可以接收到down事件,并在這時調用requestDisallowIntercept,禁止viewGroup

源碼


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 大英县| 晴隆县| 房山区| 浮梁县| 隆化县| 沧源| 乌兰县| 阳江市| 菏泽市| 隆尧县| 浦城县| 禹州市| 璧山县| 蓬安县| 义马市| 科技| 蒲城县| 黄大仙区| 泸西县| 安福县| 万全县| 胶南市| 图木舒克市| 兴海县| 岳西县| 米泉市| 淅川县| 竹山县| 西畴县| 深泽县| 阿克苏市| 克山县| 鸡西市| 车险| 乌审旗| 富宁县| 布尔津县| 宜章县| 菏泽市| 湖北省| 长子县|