摘要:在中查看源碼在看完源碼的觸摸事件源碼事件后,我們接著來看看容器類的觸摸事件。同樣的先來看源碼中的方法首先,會判斷是否不允許攔截,可以通過進行設置,默認允許攔截。
在Android-27中查看源碼:
在看完View源碼的觸摸事件(View源碼-Touch事件)后,我們接著來看看容器類View的觸摸事件。因為容器類的View都繼承自ViewGroup,所以我們在ViewGroup的源碼中來看看是如何處理觸摸事件的。
同樣的先來看ViewGroup源碼中的dispatchTouchEvent方法:
final boolean intercepted; if (actionMasked == MotionEvent.ACTION_DOWN || mFirstTouchTarget != null) { final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0; if (!disallowIntercept) { intercepted = onInterceptTouchEvent(ev); ev.setAction(action); // restore action in case it was changed } else { intercepted = false; } } else { // There are no touch targets and this action is not an initial down // so this view group continues to intercept touches. intercepted = true; }
首先,會判斷是否不允許攔截,可以通過requestDisallowInterceptTouchEvent進行設置,默認允許攔截。如果允許攔截,會調用onInterceptTouchEvent,看看該View是否攔截了觸摸事件,默認不攔截即可以將觸摸事件向子View傳遞。
接下來,如果觸摸事件沒有取消并且沒有攔截,在手指按下的時候:
final ArrayListpreorderedList = buildTouchDispatchChildList(); ... for (int i = childrenCount - 1; i >= 0; i--){ ... newTouchTarget = getTouchTarget(child); if (newTouchTarget != null) { // Child is already receiving touch within its bounds. // Give it the new pointer in addition to the ones it is handling. newTouchTarget.pointerIdBits |= idBitsToAssign; break; } resetCancelNextUpFlag(child); if (dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)) { // Child wants to receive touch within its bounds. mLastTouchDownTime = ev.getDownTime(); if (preorderedList != null) { // childIndex points into presorted list, find original index for (int j = 0; j < childrenCount; j++) { if (children[childIndex] == mChildren[j]) { mLastTouchDownIndex = j; break; } } } else { mLastTouchDownIndex = childIndex; } mLastTouchDownX = ev.getX(); mLastTouchDownY = ev.getY(); newTouchTarget = addTouchTarget(child, idBitsToAssign); alreadyDispatchedToNewTouchTarget = true; break; } ... }
按照繪制子View的順序,找到該ViewGoup的所有子view,并保存到ArrayList中。
根據視圖順序依次遍歷子View。判斷當前子view是否是TouchTarget,若是則跳出循環。否則調用dispatchTransformedTouchEvent方法,如果當前子View的dispatchTouchEvent返回為true,找到該子View在ViewGroup中的index,并將該子View作為新的TouchTarget。
清楚保存了所有子View的ArrayList。
然后在TouchTarget形成的鏈式結構中,處理觸摸事件:
// Dispatch to touch targets. if (mFirstTouchTarget == null) { // No touch targets so treat this as an ordinary view. handled = dispatchTransformedTouchEvent(ev, canceled, null,TouchTarget.ALL_POINTER_IDS); } else { // Dispatch to touch targets, excluding the new touch target if we already // dispatched to it. Cancel touch targets if necessary. TouchTarget predecessor = null; TouchTarget target = mFirstTouchTarget; while (target != null) { final TouchTarget next = target.next; if (alreadyDispatchedToNewTouchTarget && target == newTouchTarget) { handled = true; } else { final boolean cancelChild = resetCancelNextUpFlag(target.child) || intercepted; if (dispatchTransformedTouchEvent(ev, cancelChild,target.child, target.pointerIdBits)) { handled = true; } if (cancelChild) { if (predecessor == null) { mFirstTouchTarget = next; } else { predecessor.next = next; } target.recycle(); target = next; continue; } } predecessor = target; target = next; } }
如果子View沒有處理觸摸事件,則由當前的ViewGroup處理,然后返回處理結果。因為ViewGroup是View的子類,所以還是由View的dispatchTouchEvent處理。
如果子View中處理了觸摸事件,根據TouchTarget生成的鏈式結構,不斷循環,分別調用里面View的dispatchTouchEvent方法。
從上面的分析可以看出整個ViewGroup的Touch事件的整個傳遞過程如下:
是否調用了requestDisallowInterceptTouchEvent方法設置不允許攔截,默認允許攔截。若允許攔截,則再調用onInterceptTouchEvent,看是否攔截。
如果觸摸事件被攔截,則調用ViewGroup的dispatchTransformedTouchEvent方法,其實是調用View的dispatchTouchEvent方法。否則繼續向下。
當觸摸事件為MotionEvent.ACTION_DOWN時,首先獲取根據繪制順序保存了所有子View的ArrayLsit,然后再根據視圖順序去遍歷子View。
如果從TouchTarget形成的鏈表中發現該View,則跳出循環,即找到了TouchTarget。否則繼續向下。
在子View中尋找,當子View的dispatchTouchEvent方法返回為true時,則找到了新的TouchTarget,并將其添加到TouchTarget形成的鏈表中。
遍歷TouchTarget形成的鏈表,然后對鏈表里面的子View分別調用dispatchTouchEvent,最后將處理結果返回。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/72185.html
摘要:注意,事件分發是向下傳遞的,也就是父到子的順序。事件分發機制的本質是要解決,點擊事件由哪個對象發出,經過哪些對象,最終達到哪個對象并最終得到處理。表示以及分發給其中在內部完成被賦值。會自己處理事件。 目錄介紹 01.Android中事件分發順序 1.1 事件分發的對象是誰 1.2 事件分發的本質 1.3 事件在哪些對象間進行傳遞 1.4 事件分發過程涉及方法 1.5 Androi...
摘要:當不攔截事件的時候,事件會向下分發交由它的子或進行處理。表示以及分發給其中在內部完成被賦值。會自己處理事件。 目錄介紹 01.Android中事件分發順序 02.Activity的事件分發機制 2.1 源碼分析 2.2 點擊事件調用順序 2.3 得出結論 03.ViewGroup事件的分發機制 3.1 看一下這個案例 3.2 源碼分析 3.3 得出結論 04.Vie...
摘要:接下來查看方法的源碼里面的處理如下如果則返回,即該對觸摸事件不予處理。顯示了提示框的話則隱藏如果不可點擊,則移除長按事件的檢測,返回否則繼續向下走。當前是點擊事件,所以移除長按事件的檢測。關于源碼中的事件,可以參考文章源碼事件 在Android-27中查看源碼: 首先我們來查看單個View的觸摸事件的處理,在View的dispatchTouchEvent方法中看看源碼是如何處理的。 p...
閱讀 2008·2021-11-24 09:39
閱讀 1143·2021-09-10 11:25
閱讀 1769·2021-09-08 10:42
閱讀 3733·2021-09-06 15:00
閱讀 2498·2019-08-30 15:54
閱讀 3117·2019-08-29 17:08
閱讀 3272·2019-08-29 11:26
閱讀 2840·2019-08-28 18:27