編輯:關於Android編程
前段時間剛接觸過android手機開發,對它的事件傳播機制不是很了解,雖然網上也查了相關的資料,但是總覺得理解模模糊糊,似是而非,於是自己就寫個小demo測試了一下。總算搞明白了它的具體機制。寫下自己的結論,分享之,希望對初學android的人有所幫助
布局效果如圖所示:
圖1
參照上圖先說說具體得到的結論:
1) onInterceptTouchEvent負責對touch事件進行攔截,對於嵌套的view最先執行的是事件攔截方法的是最外層的那個view的onInterceptTouchEvent方法,然後依次執行子視圖的onInterceptTouchEvent,然後在執行子視圖的子視圖的事件攔截方法(當然在這裡假設所有嵌套視圖的onInterceptTouchEvent都會得到執行,讓每個視圖的onInterceptTouchEvent返回false即可)。參照上圖,所以onInterceptTouchEvent執行順序就是A--->B--->C--->D.也就是由父視圖到子視圖傳遞。總之,事件攔截機制是由父視圖開始發起對事件的攔截(出事了老子先上,兒子稍後)。參照上圖當手指觸摸事件時,父視圖A首先發起對該起事件的攔截,如果A攔截失敗,就交給它的子視圖B進行攔截;如果B攔截失敗就交給B的子視圖C再進行攔截..直到某一子視圖對該次事件攔截成功。
2)某一視圖攔截事件成功與否的判斷標識是onInterceptTouchEvent方法的返回值,當返回true的時候說明攔截成功,返回false的時候說明當前視圖對事件攔截失敗。
3)下面說說攔截成功的情況,假設C視圖對當前touch事件攔截成功。攔截成功意味著此次事件不會再傳遞到D視圖了。所以此時的D視圖的onInterceptTouchEvent就得不到運行(事件沒法到達了,還攔截誰呢?)。事件攔截成功後,緊接著就會對事件進行處理,處理的方法教給onTouchEvent方法處理。此時C視圖攔截成功,那麼緊接著就會執行C視圖的onTouchEvent方法,這是不是就意味著當前touch事件是由C視圖的onTouchEvent方法來處理的呢?這要由C視圖的onTouchEvent方法的返回值來決定。當C視圖的onTouchEvent返回true的時候,當前事件就由C全權處理,處理的當然是事件的各種action,什麼MotionEvent.ACTION_MOVE,ACTION_UP都交給了C的onTouchEvent方法進行處理。所以此時就可以在C的onTouchEvent方法中進行switch(event.getAction)判斷執行相關邏輯了。如果返回的false,說明C視圖對此事件不做處理或者處理不了,怎麼辦呢?兒子不行老爸來,於是事件就交到了B視圖的onTouchEvent方法中。同樣B對此事件處理與否還是看B的onTouchEvent返回值,具體的解釋就跟C一樣了,不復多言。
4)在A B C D的onInterceptTouchEvent和onTouchEvent都返回false的情況下,方法執行的順序依次為A.onInterceptTouchEvent-->B.onInterceptTouchEvent-->C.onInterceptTouchEvent-->D.touchEvent(最深的子視圖沒重寫onInterceptTouchEvent)-->C.touchEvent-->B.touchEvent-->A.touchEvent.也就是說攔截事件是父視圖優先有子視圖進行攔截,處理事件是子視圖優先父視圖進行處理。
總結:onInterceptTouchEvent負責對事件進行攔截,攔截成功後交給最先遇到onTouchEvent返回true的那個view進行處理。
下面將要詳細講解上面結論是怎麼得出的,准備分兩部分進行一步步講解。如果上面說的看明白的話,下面的內容就不要看了,因為會很啰嗦。
其中最後一個D是一個自定義的TextView,與A B C三個View的區別就是D只重寫了onTouchEvent方法,A B C 這三個自定義控件還重寫了onInterceptEvent方法。
D的代碼如下,A B C代碼基本上除了類名和輸出log不一樣外其余的都一樣,所以為了減少這裡只貼出其中的一個。
DView的代碼:
public class DView extends TextView{ private static String tag = D; public DView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public DView(Context context, AttributeSet attrs) { super(context, attrs); } public DView(Context context) { super(context); } @Override public boolean onTouchEvent(MotionEvent event) { Log.e(tag, --onTouchEvent--D); return false; } }
public class AView extends RelativeLayout{ private static String tag = A; public AView(Context context) { super(context); } public AView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public AView(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { Log.e(tag,--onInterceptTouchEvent--A); return false; } @Override public boolean onTouchEvent(MotionEvent event) { Log.e(tag,--onTouchEvent---A ); return false; } }
剛開始的時候重寫的方法全部返回false運行點擊的效果輸出log為:
轉換成效果圖為:
從此圖可以看出,onInterceptTouchEvent事件的執行順序是由父控件到子控件,並且優先於自己控件的onTouchEvent方法執行,onTouchEvent事件執行的順序正好相反由子控件到父控件。注意由於此時都返回了false,是沒有哪一個view來處理此次的touch事件的各個ACTION的,這也是為什麼onTouchEvent為什麼會一直傳遞到A的原因。所以ACTION_MOVE和ACTION_UP等事件得不到相應(處理),此種情況下即使你在D的onTouchEvent方法裡面寫了如下代碼,也不會得到執行。
if(event.getAction()==MotionEvent.ACTION_MOVE){ Log.e(tag, --onTouchEvent--*****); }
轉換成效果圖為:
可以發現此時A攔截了此次Touch事件,事件不再向A的子控件B C D傳遞。此時所有的action事件比如手指移動事件ACTION_MOVE或者ACTION_UP事件啦等等事件都交給A的onTouchEvent方法去處理(當然這是在onTouchEvent方法返回true的情況下,如果返回false經過測試時不會相應這些action的)。B,C ,D控件是的事件處理攔截方法和事件處理方法是無法得到執行的。
轉換成效果圖為:
此時由B攔截了此次Touch事件,並不會向C D子控件傳遞;同樣的由於onTouchEvent事件返回為false,所以此次事件的event.getAction()的各種action都不會得到處理。
轉換成效果圖為
由於onTouchEvent事件是從子控件到父控件傳遞的,當D的onTouchEvent返回true的時候,經測試輸出效果如下
轉換成效果圖為:
經過測試發現,此時D處理了此次Touch事件的各種action,C B D是的onTouchEvent的沒有得到執行。
轉換成效果圖如下:
經過測試發現,此時事件的各個action都在CView的onTouchEvent方法得到了響應,而D的onTouchEvent是不會相應MotionEvent.ACTION_XX的。其余情況一次類推,就不在啰嗦了。經過一步步的測試得出了文章開頭的結文章有點啰嗦,希望可以對閱讀此文的人有所幫助。
Android表情功能處理方案概述1.原理和實現思路2.表情圖片顯示3.表情面板4.表情的輸入框插入和刪除5.表情添加腳本Android中表情功能,一般都不是用Image
突然對懸浮窗體感興趣,查資料做了個小Demo,效果是點擊按鈕後,關閉當前Activity,顯示懸浮窗口,窗口可以拖動,雙擊後消失。效果圖如下: 它的使用原
SeekBar是一個拖動條控件,最簡單的案例就是我們的調節音量,還有音頻視頻的播放,傳統的SeekBar樣式,如圖傳統的實現太簡單,不足以讓我們到能裝逼的地步。本來是打算
大致分是這幾步: (1)新建Android工程: HelloJni.java代碼 package com.panpass.main; public c