編輯:關於Android編程
我們查看源碼,可以看到,onInterceptTouchEvent 這個方法是viewGroup 的方法
但是 dispatchTouchEvent 和 onTouchEvent 都是view 方法。
那麼我們先寫一個View OutView(外層view)繼承ViewGroup ,MiddleView(中層View) 繼承ViewGroup ,InnerView (內層Button,Button 也是繼承的view )繼承View
既然 dispatchTouchEvent 和 onTouchEvent 是view 的方法,那麼我們在每個view 裡面重寫這兩個方法,如下,
每個方法會打印兩邊log,第一個log,是調用這個方法開始的時候,就打一句,第二個log ,是這個方法調用父類,也就說,該走的邏輯走完,並且有返回值的時候。為了log 清晰,都只是打印了 ACTION_DOWN 事件的。
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.e(TAG, dispatchTouchEvent);
break;
}
boolean flag = super.dispatchTouchEvent(ev);
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.e(TAG, dispatchTouchEvent: + flag);
break;
}
return flag;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.e(TAG, onTouchEvent);
break;
}
boolean flag = super.onTouchEvent(ev);
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.e(TAG, onTouchEvent: + flag);
break;
}
return flag;
}
輸出的log 如下
toucheventdemo E/OutView﹕ dispatchTouchEvent
toucheventdemo E/MiddleView﹕ dispatchTouchEvent
toucheventdemo E/InnerView﹕ dispatchTouchEvent
toucheventdemo E/InnerView﹕ onTouchEvent
toucheventdemo E/InnerView﹕ onTouchEvent:true
toucheventdemo E/InnerView﹕ dispatchTouchEvent:true
toucheventdemo E/MiddleView﹕ dispatchTouchEvent:true
toucheventdemo E/OutView﹕ dispatchTouchEvent:true
可以看到前三個雖然都是直接都是dispatchTouchEvent 方法裡面的log 打印的,但是log並沒有返回值,也就是說,都是執行的方法裡面第一句log,
但是當執行到InnerView﹕ dispatchTouchEvent 的時候,又執行了InnerView﹕ onTouchEvent 的方法
其實是這樣的, boolean flag = super.dispatchTouchEvent; 這一句,super 中,執行的dispatchTouchEvent ,
其實會做兩件事
1,第一件事,是看當前的view 有沒有子view,如果有子view,並且會判斷當前的觸摸點是否在子view 上面,如果在的話,那麼就會調用子view的dispatchTouchEvent ,然後一層一層往裡面調用,
2.一直調用到沒有子view 的時候,然後停止dispatchTouchEvent ,因為InnerView 是繼承的view,當然沒有子view,然後這個時候,就開始調用子view 的onTouchEvent。
onTouchEvent 返回 true ,那麼當前view 的dispatchTouchEvent 也會返回view, 此時,就會講dispatchTouchEvent 的分發結果反饋給父view,當前view 的父view 的dispatchTouchEvent 也會返回true,以此類推,返回到最外層,
那麼如果裡層的view 返回的true 那如果最裡層的view onTouchEvent返回的是false 那?我們將裡層的view 繼承改成View,
toucheventdemo E/OutView﹕ dispatchTouchEvent
toucheventdemo E/MiddleView﹕ dispatchTouchEvent
toucheventdemo E/InnerView﹕ dispatchTouchEvent
toucheventdemo E/InnerView﹕ onTouchEvent
toucheventdemo E/InnerView﹕ onTouchEvent:false
toucheventdemo E/InnerView﹕ dispatchTouchEvent:false
toucheventdemo E/MiddleView﹕ onTouchEvent
toucheventdemo E/MiddleView﹕ onTouchEvent:false
toucheventdemo E/MiddleView﹕ dispatchTouchEvent:false
toucheventdemo E/OutView﹕ onTouchEvent
toucheventdemo E/OutView﹕ onTouchEvent:false
toucheventdemo E/OutView﹕ dispatchTouchEvent:false
我們會發現,當裡層的view ,onTouchEvent:false 的時候,那麼裡層的dispatchTouchEvent 也是false ,並且此時立馬會調用,裡層view 的父view(也就是MiddleView) 的 onTouchEvent 事件,MiddleView的onTouchEvent 也返回false ,那麼此時MiddleView dispatchTouchEvent 也會是false,然後接著調用了最外層 OutView onTouchEvent 方法。
從這兩個小試驗,你能看出,dispatchTouchEvent 的返回結果是怎麼得來的嗎?
分兩種情況
當前 沒有子view 那麼當前view 的 dispatchTouchEvent 結果就是當前view onTouchEvent 的結果
當前view 有子view, 此時又分兩種情況
子view 的 dispatchTouchEvent 返回false 那麼當前view 的 dispatchTouchEvent 結果參照第一種情況,也就是當前view onTouchEvent 執行 ,並且dispatchTouchEvent 的結果是 當前view 的 onTouchEvent 的結果 子view 的 onTouchEvent 返回true ,那麼 此時當前view 的onTouchEvent 的不執行 直接直接返回的是子view 的 dispatchTouchEvent 返回的view(具體這裡為什麼說還要判斷當前觸摸的點還有沒有子view,你可以自己試驗,觸摸MiddleView 之內,InnerView之外的區域,看會不會打印InnerView 裡面的log )
首先翻譯api onInterceptTouchEvent : 攔截TouchEvent 事件。
應為onInterceptTouchEvent 是viewGroup 的方法,那麼我們重寫OutView 和 MiddleView 的onInterceptTouchEvent方法
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.e(TAG, onInterceptTouchEvent);
break;
}
boolean flag = super.onInterceptTouchEvent(ev);
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.e(TAG, onInterceptTouchEvent: + flag);
break;
}
return flag;
}
然後運行,點擊InnerView 看log
toucheventdemo E/OutView﹕ dispatchTouchEvent
toucheventdemo E/OutView﹕ onInterceptTouchEvent
toucheventdemo E/OutView﹕ onInterceptTouchEvent:false
toucheventdemo E/MiddleView﹕ dispatchTouchEvent
toucheventdemo E/MiddleView﹕ onInterceptTouchEvent
toucheventdemo E/MiddleView﹕ onInterceptTouchEvent:false
toucheventdemo E/InnerView﹕ dispatchTouchEvent
toucheventdemo E/InnerView﹕ onTouchEvent
toucheventdemo E/InnerView﹕ onTouchEvent:false
toucheventdemo E/InnerView﹕ dispatchTouchEvent:false
toucheventdemo E/MiddleView﹕ onTouchEvent
toucheventdemo E/MiddleView﹕ onTouchEvent:false
toucheventdemo E/MiddleView﹕ dispatchTouchEvent:false
toucheventdemo E/OutView﹕ onTouchEvent
toucheventdemo E/OutView﹕ onTouchEvent:false
toucheventdemo E/OutView﹕ dispatchTouchEvent:false
我們會發現,在所有的具體執行 dispatchTouchEvent 的方法一開始執行,都會先執行當前view 的onInterceptTouchEvent 結果,onInterceptTouchEvent 的默認返回值是false
現在我們修改一下MiddleView 的onInterceptTouchEvent 返回值為true 看代碼
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.e(TAG, onInterceptTouchEvent);
break;
}
boolean flag = super.onInterceptTouchEvent(ev);
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.e(TAG, onInterceptTouchEvent: + true);
break;
}
return true;
}
然後我們運行,看log
toucheventdemo E/OutView﹕ dispatchTouchEvent
toucheventdemo E/OutView﹕ onInterceptTouchEvent
toucheventdemo E/OutView﹕ onInterceptTouchEvent:false
toucheventdemo E/MiddleView﹕ dispatchTouchEvent
toucheventdemo E/MiddleView﹕ onInterceptTouchEvent
toucheventdemo E/MiddleView﹕ onInterceptTouchEvent:true
toucheventdemo E/MiddleView﹕ onTouchEvent
toucheventdemo E/MiddleView﹕ onTouchEvent:false
toucheventdemo E/MiddleView﹕ dispatchTouchEvent:false
toucheventdemo E/OutView﹕ onTouchEvent
toucheventdemo E/OutView﹕ onTouchEvent:false
toucheventdemo E/OutView﹕ dispatchTouchEvent:false
我們會發現,當修改了,MiddleView 的onInterceptTouchEvent 返回結果是true 之後,
本來應該向InnerView 做分發的那部分log 沒有了。然後直接執行了當前MiddleView 的 onTouchEvent 結果,然後執行完
onTouchEvent結果,之後,當前view 的dispatchTouchEvent 的結果也出來了,然後緊接著把這個有反饋給了OutView 外層view 的,並且執行的原理和我們前面只重寫 dispatchTouchEvent onTouchEvent 的原理一樣。
到這裡你也應該知道這個onInterceptTouchEvent 是干嘛的吧,他其實就是攔截事件是否要繼續往下傳遞,如果返回true ,那麼代表 事件被當前view 攔截,並且不向下傳遞,直接執行當前view 的 onTouchEvent 事件。
onInterceptTouchEvent : 攔截事件,判斷是否向下傳遞。 返回true 代表攔截,返回false 代表不攔截
dispatchTouchEvent : 事件分發,管理事件的分發,向子view 分發事件,並且,根據得到的子view的事件處理情況,來判斷是否響應當前view的 觸摸事件 返回true,代表當前view 的或者子view 已經處理事件,告訴父view, 不需要處理事件,返回false ,代表當前view 或者子view 也沒有處理事件,告訴父view,可以去處理事件了。
onTouchEvent : 事件的處理,在此方法內處理事件。 返回true ,代表當前view 處理了事件,false 代表當前view 沒有處理事件。
public void requestDisallowInterceptTouchEvent(boolean disallowIntercept)
首先翻譯: 請求禁止攔截觸摸事件 ,字面理解,就是禁止吊我們的攔截,也就是禁止吊這個方法,onInterceptTouchEvent
那麼我們現在把所有的onInterceptTouchEvent dispatchTouchEvent onTouchEvent 都加上move 事件。
代碼如下,
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.e(TAG, onInterceptTouchEvent ACTION_DOWN);
break;
case MotionEvent.ACTION_MOVE:
Log.e(TAG, onInterceptTouchEvent ACTION_MOVE);
break;
}
boolean flag = super.onInterceptTouchEvent(ev);
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.e(TAG, onInterceptTouchEvent ACTION_DOWN: + flag);
break;
case MotionEvent.ACTION_MOVE:
Log.e(TAG, onInterceptTouchEvent ACTION_MOVE: + flag);
break;
}
return flag;
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.e(TAG, dispatchTouchEvent ACTION_DOWN);
break;
case MotionEvent.ACTION_MOVE:
Log.e(TAG, dispatchTouchEvent ACTION_MOVE);
break;
}
boolean flag = super.dispatchTouchEvent(ev);
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.e(TAG, dispatchTouchEvent ACTION_DOWN: + flag);
break;
case MotionEvent.ACTION_MOVE:
Log.e(TAG, dispatchTouchEvent ACTION_MOVE: + flag);
break;
}
return flag;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.e(TAG, onTouchEvent ACTION_DOWN);
break;
case MotionEvent.ACTION_MOVE:
Log.e(TAG, onTouchEvent ACTION_MOVE );
break;
}
boolean flag = super.onTouchEvent(ev);
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.e(TAG, onTouchEvent ACTION_DOWN: + flag);
break;
case MotionEvent.ACTION_MOVE:
Log.e(TAG, onTouchEvent ACTION_MOVE: + flag);
break;
}
return flag;
}
並且給 MiddleView 的onInterceptTouchEvent 方法中加上 requestDisallowInterceptTouchEvent(true);
如下
public boolean onInterceptTouchEvent(MotionEvent ev) {
//加上此句
requestDisallowInterceptTouchEvent(true);
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.e(TAG, onInterceptTouchEvent ACTION_DOWN);
break;
case MotionEvent.ACTION_MOVE:
Log.e(TAG, onInterceptTouchEvent ACTION_MOVE);
break;
}
boolean flag = super.onInterceptTouchEvent(ev);
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.e(TAG, onInterceptTouchEvent ACTION_DOWN: + flag);
break;
case MotionEvent.ACTION_MOVE:
Log.e(TAG, onInterceptTouchEvent ACTION_MOVE: + flag);
break;
}
return flag;
}
那麼現在我們觸摸,然後看log ,可能log 比較多,但是希望大家慢慢仔細看。
toucheventdemo E/OutView﹕ dispatchTouchEvent ACTION_DOWN
toucheventdemo E/OutView﹕ onInterceptTouchEvent ACTION_DOWN
toucheventdemo E/OutView﹕ onInterceptTouchEvent ACTION_DOWN:false
toucheventdemo E/MiddleView﹕ dispatchTouchEvent ACTION_DOWN
toucheventdemo E/MiddleView﹕ onInterceptTouchEvent ACTION_DOWN
toucheventdemo E/MiddleView﹕ onInterceptTouchEvent ACTION_DOWN:false
toucheventdemo E/InnerView﹕ dispatchTouchEvent ACTION_DOWN
toucheventdemo E/InnerView﹕ onTouchEvent ACTION_DOWN
toucheventdemo E/InnerView﹕ onTouchEvent ACTION_DOWN:true
toucheventdemo E/InnerView﹕ dispatchTouchEvent ACTION_DOWN:true
toucheventdemo E/MiddleView﹕ dispatchTouchEvent ACTION_DOWN:true
toucheventdemo E/OutView﹕ dispatchTouchEvent ACTION_DOWN:true
//從這裡開始move事件。
toucheventdemo E/OutView﹕ dispatchTouchEvent ACTION_MOVE
toucheventdemo E/MiddleView﹕ dispatchTouchEvent ACTION_MOVE
toucheventdemo E/InnerView﹕ dispatchTouchEvent ACTION_MOVE
toucheventdemo E/InnerView﹕ onTouchEvent ACTION_MOVE
toucheventdemo E/InnerView﹕ onTouchEvent ACTION_MOVE:true
toucheventdemo E/InnerView﹕ dispatchTouchEvent ACTION_MOVE:true
toucheventdemo E/MiddleView﹕ dispatchTouchEvent ACTION_MOVE:true
toucheventdemo E/OutView﹕ dispatchTouchEvent ACTION_MOVE:true
toucheventdemo E/OutView﹕ dispatchTouchEvent ACTION_MOVE
toucheventdemo E/MiddleView﹕ dispatchTouchEvent ACTION_MOVE
toucheventdemo E/InnerView﹕ dispatchTouchEvent ACTION_MOVE
toucheventdemo E/InnerView﹕ onTouchEvent ACTION_MOVE
toucheventdemo E/InnerView﹕ onTouchEvent ACTION_MOVE:true
toucheventdemo E/InnerView﹕ dispatchTouchEvent ACTION_MOVE:true
toucheventdemo E/MiddleView﹕ dispatchTouchEvent ACTION_MOVE:true
toucheventdemo E/OutView﹕ dispatchTouchEvent ACTION_MOVE:true
我們可以看處理啊,第一次是ACTION_DOWN 事件的時候一切正常,(InnerView 是繼承的 Button,所以onTouchEvent 返回的是true)
但是從ACTION_MOVE 你會發現,所有的onInterceptTouchEvent 事件全部沒有了,其實,也就這個方法也就是這個方法起的作用,
新手弄第三方類庫也許會很納悶,有時弄幾天都不行。那就讓我帶大家10分鐘做一個簡單的短信驗證吧!1.首先上Mob官網注冊賬號:http://www.mob.com/2.下載
Android提供了強大的事件處理機制,主要包括兩大類:1,基於監聽的事件處理機制:主要做法是為Android界面組件綁定特定的事件監聽器2,基於回調的事件處理機制:主要
記得之前有朋友在留言裡讓我寫一篇關於沉浸式狀態欄的文章,正巧我確實有這個打算,那麼本篇就給大家帶來一次沉浸式狀態欄的微技巧講解。其實說到沉浸式狀態欄這個名字我也是感到很無
前言在Android開發過程中,我發現很多安卓源代碼裡應用了設計模式,比較常用的有適配器模式(各種adapter),建造者模式(Alert Dialog的構建)等等。雖然