<br />
一個簡單問題:點擊Activity中的一個TextView山涡,觸摸事件是怎樣分發(fā)傳遞的
View的事件傳遞由三個重要方法完成,dispatchTouchEvent(), onInterceptTouchEvent() 和 onTouchEvent()箍土。
public boolean dispatchTouchEvent(MotionEvent event)
用來進行事件的分發(fā)。如果事件能夠傳遞給當前的View罐监,那么此方法一定會被調(diào)用吴藻,返回結(jié)果受當前View的onTouchEvent和下級的dispatchTouchEvent方法的影響,表示是否消耗當前事件弓柱。
<br />
public boolean onInterceptTouchEvent(MotionEvent event)在dispatchTouchEvent方法內(nèi)部調(diào)用沟堡,用來判斷是否攔截某一事件侧但,返回結(jié)果表示是否攔截。如果當前View攔截了某個事件航罗,那么在同一個事件序列當中禀横,此方法不會被再次調(diào)用。
<br />
public boolean onTouchEvent(MotionEvent event)在dispatchTouchEvent方法內(nèi)部調(diào)用粥血,用來處理點擊事件柏锄。返回結(jié)果表示是否消耗當前事件,如果不消耗复亏,則在同一個事件序列中趾娃,當前View無法再次接收到事件。
<br />
上述三個方法到底是什么關(guān)系呢缔御?它們的關(guān)系可以用如下偽代碼表示
public boolean dispatchTouchEvent(TouchEvent event) {
if (onInterceptTouchEvent(event)) {
consume = onTouchEvent(event);
} else {
consume = child.dispatchTouchEvent(event);
}
return consume;
}
<br />
同一個事件序列是指從手指接觸屏幕的那一刻起抬闷,到手指離開屏幕的那一刻結(jié)束,在這個過程中所產(chǎn)生的一系列事件耕突。
這個事件序列以down事件開始笤成,中間含有數(shù)量不定的move事件,最終以up事件結(jié)束眷茁。
<br />
事件的傳遞規(guī)則
- 對于一個根ViewGroup來說炕泳,點擊事件產(chǎn)生后,首先會傳遞給它蔼卡,它的dispatchTouchEvent就會被調(diào)用
- 如果這個ViewGroup的onInterceptTouchEvent返回true喊崖,就表示它要攔截當前事件,接下來事件會交給這個ViewGroup處理雇逞,即它的onTouchEvent會調(diào)用
- 如果這個ViewGroup的onInterceptTouchEvent返回false荤懂,則表示它不攔截當前事件,這樣事件會傳遞給子控件塘砸,子控件的dispatchTouchEvent會被調(diào)用节仿,如此反復(fù)直到事件被處理
<br />
事件的傳遞順序
- 一個點擊事件產(chǎn)生后,它的傳遞過程遵循如下順序:Activity -> Window -> View
- 一個事件總是先傳遞給Activity掉蔬,Activity再傳遞給Window廊宪,最后Window再傳遞給頂級View,頂級View接收事件后女轿,就會按照事件分發(fā)機制來分發(fā)事件箭启。
<br />
事件的處理過程
- 由事件的分發(fā)過程可知,事件一般會層層傳遞給最終的View蛉迹,如一個Button或者EditText傅寡,由它的onTouchEvent處理
- 子View的onTouchEvent的返回值是true還是false,表示它是否處理這個事件
- View的onTouchEvent默認都會消耗事件,除非它是不可點擊的荐操,比如TextView芜抒,它的onTouchEvent默認返回false
- 如果子View的onTouchEvent返回false,它不處理事件的話托启,那么它的父容器的onTouchEvent會被調(diào)用宅倒,這個事件會拋給父容器處理,以此類推屯耸。
- 如果所有元素都不處理這個事件拐迁,那么這個事件最終會傳遞給Activity處理,即Activity的onTouchEvent會被調(diào)用疗绣。
<br />