Android 事件分發機制原始碼分析
阿新 • • 發佈:2022-04-19
if(MotionEvent.ACTION_DOWN || mFirstTouchTarget != null){ //初次的down事件到來的時候,只有父view具有決定事件是否攔截的權利。因為此時的disallowIntercept初始值是false,原因是down事件之前會重置這個標誌位 final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0; //第一個down進來下面這個if條件是成立的,因此父view的onInterceptTouchEvent方法就決定了是否攔截 if(!disallowIntercept){ intercepted = onInterceptTouchEvent(ev) }else{ //這個條件是子view要求父view不要攔截,其實就是後續的move和up事件不要攔截,因為能進到這個地方不可能是down事件並且mFirstTouchTarget != null intercepted = false; } }else{ //進到這個地方說明事件是move或者up並且mFirstTouchTarget == null。 //move或者up能進到這個地方說明mFirstTouchTarget == null,那麼就意味著要麼down被父view消費了(down事件被父view攔截了或者子view不處理down事件又把down事件交給父view處理) //要麼就是在move或者up的事件子view要求父view進行攔截並且父view攔截了,這樣也會導致mFirstTouchTarget == null成立。這樣的話子view就再也拿不到事件了 intercepted = true } //新的事件會重置這兩個值 TouchTarget newTouchTarget = null; boolean alreadyDispatchedToNewTouchTarget = false; //只有不攔截才會命中 if(!canceled && !intercepted){ //只有down事件才會進行分發 if (actionMasked == MotionEvent.ACTION_DOWN){ for(){ //利用迴圈遍歷按住的子view if (dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)) { //如果找到了處理down事件的子view 就會在addTouchTarget方法裡面把 mFirstTouchTarget的值設定成非空 newTouchTarget = addTouchTarget(child, idBitsToAssign); //把已經消費的標記為設定成true alreadyDispatchedToNewTouchTarget = true; break; } } } } //上面已經解釋過mFirstTouchTarget==null的原因了,1、down事件被父view消費掉了 2、子view的move事件交給了父view攔截並且攔截了 if(mFirstTouchTarget == null){ //自己處理事件 handled = dispatchTransformedTouchEvent(ev, canceled, null, TouchTarget.ALL_POINTER_IDS); }else { //子view處理事件 TouchTarget target = mFirstTouchTarget; while(target != null){ if (alreadyDispatchedToNewTouchTarget && target == newTouchTarget) { //如果當前事件是down並且down事件被子view處理了這個就會成立 handled = true; }else{ //事件來的時候會重置alreadyDispatchedToNewTouchTarget = false 能進到這裡說明1、down事件被子view處理並且此時的事件不是down事件。 //如果move或者up事件被攔截了cancelChild則是true否則false final boolean cancelChild = resetCancelNextUpFlag(target.child)|| intercepted; //交給自己或者子view去處理 if (dispatchTransformedTouchEvent(ev, cancelChild, target.child, target.pointerIdBits)) { handled = true; } //如果是自己處理也就是move事件被父view攔截了 if (cancelChild) { //mFirstTouchTarget設定成next 單指為null mFirstTouchTarget = next } } target = next; } } }