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

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

View的事件分發機制

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

  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

源碼


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 林口县| 盐山县| 潞城市| 邯郸市| 霍林郭勒市| 响水县| 盐津县| 广汉市| 金华市| 深泽县| 离岛区| 香河县| 铁岭县| 珠海市| 土默特右旗| 布拖县| 威信县| 莲花县| 右玉县| 蓝田县| 社旗县| 沁水县| 泗水县| 华坪县| 鄯善县| 安丘市| 苍梧县| 托克托县| 英吉沙县| 固镇县| 武冈市| 普安县| 师宗县| 广平县| 莲花县| 弥渡县| 红桥区| 皮山县| 桦南县| 治县。| 泸水县|