對於ViewGroup
來講,與事件分發相關的方法包括:android
public boolean dispatchTouchEvent(MotionEvent event)
public boolean onInterceptTouchEvent(MotionEvent event)
public boolean onTouchEvent(MotionEvent event)
複製代碼
對於View
來講,與事件分發相關的方法包括:bash
public boolean dispatchTouchEvent(MotionEvent event)
public boolean onTouchEvent(MotionEvent event)
複製代碼
Down
分發的理解對於Down
分發的過程,網上看了不少的例子和圖,可是都沒能好好理解,最後仍是本身總結了一種方案,這個方案的核心就是染色:函數
View
樹上每一個節點都是白色的。dispatchTouchEvent
時,在返回以前都會有一個返回值,若是這個返回值爲真,那麼它本身就會變成紅色。dispatchTouchEvent
時,它既是在嘗試給子節點進行染色,也是在嘗試給本身着色,當某個子節點的dispatchTouchEvent
方法返回時,取該子節點的顏色對本身進行着色;若是遍歷完它全部的子節點,它仍然沒有變成紅色,那麼調用它本身的onTouchEvent
,若是返回true
,那麼把本身染成紅色。ViewGroup/View
來講,有可能染色成功只包括兩種途徑:子節點的dispatchTouchEvent
返回時,取子節點的顏色對本身着色;經過本身的onTouchEvent
方法來着色。而且,只有前一種途徑不成功時纔會用後一種途徑。dispatchTouchEvent
來染色或者經過本身的onTouch
來染色,它會直接返回。從僞代碼來看:ui
public Color color = white;
public boolean dispatchTouchEvent(MotionEvent event) {
int childCount = getChildCount;
for (i = childCount - 1; i >= 0; i--) {
View child = getChildAt(i);
boolean result = child.dispatchTouchEvent(event);
if (result) {
color = RED;
return true;
}
}
boolean touchRes = onTouchEvent(event);
if (touchRes) {
color = RED;
}
return touchRes;
}
複製代碼
在Down
事件分發完後,咱們能夠發現這麼個現象。spa
Down
分發的特色對於一個沒有重寫以上關鍵方法而且位於View
樹上的ViewGroup/View
來講,它Down
事件的分發具備如下幾個特色:code
dispatchTouchEvent
dispatchTouchEvent
是否被回調,由它的父容器決定的。dispatchTouchEvent
被調用時,它會先逆序依次調用下一級子節點的dispatchTouchEvent
方法。dispatchTouchEvent
返回了true
,那麼不會繼續調用剩餘未遍歷子節點的dispatchTouchEvent
,而且它自身的onTouchEvent
不會被回調。onInterceptTouchEvent
只有ViewGroup
纔有,它是否被回調取決於dispatchTouchEvent
是否被回調。xml
onTouchEvent
onTouchEvent
是由本身回調的,是否被回調,必須同時知足如下兩個條件:事件
dispatchTouchEvent
被回調。View
樹的葉節點dispatchTouchEvent
都返回false
。Move/Up
分發在Move/Up
事件分發的時候,其實就是根據以前着色的結果來往下傳遞事件,它的傳遞只須要遵循下面的原則:只會分發給紅色的節點,遇到白色的節點就中止往下分發。ip
咱們舉一個簡單的例子: utf-8
ViewGroup1
返回true
。Root
調用ViewGroup1
的dispatchTouchEvent
,而ViewGroup1
此時是白色,所以它繼續調用它的子節點,也就是View21
的dispatchTouchEvent
,可是View21
沒有子節點,所以它調用本身的onTouchEvent
,它的dispatchTouchEvent
方法返回,而此時,ViewGroup2
全部的子節點都遍歷完了,它依然沒有變成紅色,所以它調用本身的onTouchEvent
,因爲該方法返回false
,所以它也返回了,而且在返回時依然是白色。接下來Root
取ViewGroup2
的顏色對本身着色,着色完成以後發現本身仍然是白色,那麼它就繼續調用有可能使本身染色成功的方法,ViewGroup1
的dispatchTouchEvent
,因爲它的dispatchTouchEvent
返回true
,所以它會把本身染成紅色,因爲它已經變成紅色了,那麼它也沒有權利對子節點進行染色,所以它的dispatchTouchEvent
返回,Root
收到返回值時,取ViewGroup1
的顏色對本身進行着色,結果它發現本身是紅色了,那麼Root
也不會調用任何可能對本身染色的方法,而是直接返回了。ROOT
和ViewGroup1
變爲紅色節點。只要理解了上面的思想,其實各類狀況均可以對應到,下面的例子只是爲了讓你們可以證實本身的想法是否正確罷了,因此就不過多解釋了:
<?xml version="1.0" encoding="utf-8"?>
<com.example.lizejun.repoviews.LogFrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:tag="ViewGroup$Root"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.lizejun.repoviews.MainActivity">
<com.example.lizejun.repoviews.LogFrameLayout
android:tag="ViewGroup1"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.lizejun.repoviews.LogTextView
android:tag="ViewGroup1$View1"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.example.lizejun.repoviews.LogTextView
android:tag="ViewGroup1$View2"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</com.example.lizejun.repoviews.LogFrameLayout>
<com.example.lizejun.repoviews.LogFrameLayout
android:tag="ViewGroup2"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.lizejun.repoviews.LogTextView
android:tag="ViewGroup2$View"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</com.example.lizejun.repoviews.LogFrameLayout>
</com.example.lizejun.repoviews.LogFrameLayout>
複製代碼
ViewGroup2
的dispatchTouchEvent
返回false
ViewGroup2
的dispatchTouchEvent
返回true
ViewGroup1
下的孩子節點View2
返回了false
ViewGroup1
下的孩子節點View2
返回了true
ViewGroup2
的onTouchEvent
返回了false
ViewGroup2
的onTouchEvent
返回了true
ViewGroup1
下的孩子節點View2
返回了false
ViewGroup1
下的孩子節點View2
返回了true