編輯:關於android開發
Touch事件分發中只有兩個主角:ViewGroup和View。Activity的Touch事件事實上是調用它內部的ViewGroup的Touch事件,可以直接當成ViewGroup處理。View在ViewGroup內,ViewGroup也可以在其他ViewGroup內,這時候把內部的ViewGroup當成View來分析。
ViewGroup的相關事件有三個:onInterceptTouchEvent、dispatchTouchEvent、onTouchEvent。
View的相關事件只有兩個:dispatchTouchEvent、onTouchEvent。
先分析ViewGroup的處理流程:首先得有個結構模型概念:ViewGroup和View組成了一棵樹形結構,最頂層為Activity的ViewGroup,下面有若干的ViewGroup節點,每個節點之下又有若干的ViewGroup節點或者View節點,依次類推。如圖:當一個Touch事件(觸摸事件為例)到達根節點,即Acitivty的ViewGroup時,它會依次下發,下發的過程是調用子View(ViewGroup)的dispatchTouchEvent方法實現的。簡單來說,就是ViewGroup遍歷它包含著的子View,調用每個View的dispatchTouchEvent方法,而當子View為ViewGroup時,又會通過調用ViwGroup的dispatchTouchEvent方法繼續調用其內部的View的dispatchTouchEvent方法。上述例子中的消息下發順序是這樣的:①-②-⑤-⑥-⑦-③-④。dispatchTouchEvent方法只負責事件的分發,它擁有boolean類型的返回值,當返回為true時,順序下發會中斷。在上述例子中如果⑤的dispatchTouchEvent返回結果為true,那麼⑥-⑦-③-④將都接收不到本次Touch事件。
話說還是上代碼驗證,寫過了就
ViewGroup的dispatchTouchEvent是真正在執行“分發”工作,而View的dispatchTouchEvent方法,並不執行分發工作,或者說它分發的對象就是自己,決定是否把touch事件交給自己處理,而處理的方法,便是onTouchEvent事件.
public class Btn extends Button { public Btn(Context context) { super(context); } public Btn(Context context, AttributeSet attrs) { super(context, attrs); } public Btn(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { Log.i("Btn","dispatchTouchEvent "+ev.getAction()+""); return super.dispatchTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { Log.i("Btn","onTouchEvent "+event.getAction()+""); return super.onTouchEvent(event); } }
main.xml
日志都添加完畢,現在我們點擊btn 看看執行順序.
可見默認情況下 viewgroup會通過dispatchTouchEvent一直向下分發事件. dispatchTouchEvent 過程中調用onInterceptTouchEvent看viewgroup自己會不會對事件進行攔截.
先是down 然後是up.直到葉子節點view 時候調用其onTouchEvent 然後 在down的時候調用 onclicklistener.
現在我們來驗證dispatchTouchEvent 返回值對事件分發的影響. 正常情況dispatchTouchEvent 默認為super.dispatchTouchEvent .return true; 則事件不再往底層傳遞.而ontouch 事件也應該由改view 或者viewgroup的來消費.
測試ONE (btnLinerLayout的dispatchTouchEvent 分別 返回 false 和 true)
false 情況:
可以看到down事件在btnLinerLayout 停止分發了. (btn dispatchTouchEvent 沒執行) , 事件首先被rootLinerLayout的onTouchEvent處理 然後 返回給上級的TestActivity onTouchEvent處理. 最後一個onTouchEvent 被定為後續事件的處理著,up 事件就 直接交給TestActivity來處理.
有一點不明白: TestActivity的onTouchEvent 執行完後 btn的onclickListener 不執行了 ,||
true 情況:
true 就與預想的一樣 事件不在往底層傳遞.並且沒有地方消費onTouchEvent...||
這時候如果btnLinerLayout onTouchEvent 返回true 則上層的onTouchEvent 會被依次執行. down直接則直接交給TestActivity.
如果單獨把btnLinerLayoutonTouchEvent 返回true.【dispatchTouchEvent 為super】 則結果和默認的一樣.事件最後傳遞給Btn 葉子節點消費.執行其onTouchEvent 並且down的時候直接把事件交給btn的onTouchEvent 並且執行 onClickLlistener
總結 只要dispatchTouchEvent 不為super 那麼就會中斷事件的傳遞.只不過false的情況 事件的響應父級會默認一次往上都響應到onTouchEvent裡面. 並且隨後的up事件會直接交給頂層目標來處理. true的話事件也會依次回傳但是都不響應.
測試two(BtnLinerLayout的onInterceptTouchEvent 返回 true ,dispatchTouchEvent 為 super | true | false):
正常情況.onInterceptTouchEvent 返回true 代表事件被當前viewgroup攔截,和消費
dispatchTouchEvent 默認super():
BtnLinerLayout執行順序為dispatchTouchEvent-onInterceptTouchEvent -onTouchEvent 的確自己能處理onTouchEvent了.並且依次傳遞給上層的onTouchEvent
dispatchTouchEvent 為 true
事件被攔截 並且 沒有繼續下發.到BtnLinerLayout 截至了.
dispatchTouchEvent 為 false
事件被攔截.沒有繼續下發.當前也沒有消費 一次交由父類 onTouchEvent響應. 最後 事件交由頂層的TestActicty onTouchEvent執行 後續down事件直接轉給 TestActivity
。。。這情況和直接設置為dispatchTouchEvent 為false onInterceptTouchEvent 為默認一樣.向上傳遞相應 默認都執行onTouchEvent.
由上面2輪測試可以看出
onInterceptTouchEvent 為true . 事件會被當前的viewgruop消費到onTouchEvent中.默認情況下依次響應到父類的onTouchEvent中.最後到頂層.隨後的up事件直接交給頂層處理.
HBase Java編程示例HelloWorld.zippackage elementary;import java.io.IOException;import java
我的android學習經歷15,android學習經歷15利用Intent實現有返回結果的頁面跳轉 主要用的方法: (1)Intent的構造方法:intent(當前界面對
搭建郵件服務器postfix 步驟(轉)學習一個服務的流程; 1、此服務器的概述:名字,功能,特點,端口號 2、安裝 3、配置文件的位置 4、服務啟動關閉腳本,查
《Android動畫高手成長記》跳跳球效果 在介紹本文動畫效果實現之前,先來介紹屬性動畫相關的幾個知識點。 ValueAnimator與ObjectAnimator。