在網上搜到了很有意思的一道題,仔細想一下這道題。
答案是如果有action_move操作,那麼action_down傳遞給c,action_move和action_up都傳遞給b,a沒有獲得任何事件。如果沒有執行滑動操作,那麼action_down和action_up都傳遞給c。
因為事件會先從a-》b依次執行
onintercepttouchevent,如果那一邊返回了true,就說明該層viewgrou攔截了事件傳遞.
而現在b只對action_move這個事件做攔截,如果b攔截了action_move這個事件,那麼後續所有的事件都由b來消費。
如果b沒有對action_move這個事件做攔截,那麼後續所有的事件還是由c來消費。
這裡追加個問題。
也就是當一層viewgrou決定攔截乙個事件,那麼後續的事件都會由他來消費嗎?
不一定,這裡b view的onintercepttouchevent改一下,如下:
@override
public boolean onintercepttouchevent(motionevent ev)
return super.onintercepttouchevent(ev);
}
攔截的是第乙個action_down事件。
執行一下程式,原本以為結果是action_down和action_up還有action_move都會由b來執行,但是結果卻是b只執行了action_down,那麼action_up和action_move去**了?
這裡需要理解下ontouchevent方法執行了什麼?因為ontouchevent如果返回true的情況後續事件才會繼續消費,而在view的
ontouchevent原始碼
public boolean ontouchevent(motionevent event)
mprivateflags3 &= ~pflag3_finger_down;
// a disabled view that is clickable still consumes the touch
// events, it just doesn't respond to them.
return clickable;
}if (mtouchdelegate != null)
}if (clickable || (viewflags & tooltip) == tooltip)
if (!clickable)
boolean prepressed = (mprivateflags & pflag_prepressed) != 0;
if ((mprivateflags & pflag_pressed) != 0 || prepressed)
if (prepressed)
if (!mhasperformedlongpress && !mignorenextupevent)
if (!post(mperformclick)) }}
if (munsetpressedstate == null)
if (prepressed) else if (!post(munsetpressedstate))
removetapcallback();
}mignorenextupevent = false;
break;
case motionevent.action_down:
if (event.getsource() == inputdevice.source_touchscreen)
mhasperformedlongpress = false;
if (!clickable)
if (performbuttonactionontouchdown(event))
// walk up the hierarchy to determine if we're inside a scrolling container.
boolean isinscrollingcontainer = isinscrollingcontainer();
// for views inside a scrolling container, delay the pressed feedback for
// a short period in case this is a scroll.
if (isinscrollingcontainer)
mpendingcheckfortap.x = event.getx();
mpendingcheckfortap.y = event.gety();
postdelayed(mpendingcheckfortap, viewconfiguration.gettaptimeout());
} else
break;
case motionevent.action_cancel:
if (clickable)
removetapcallback();
removelongpresscallback();
mincontextbuttonpress = false;
mhasperformedlongpress = false;
mignorenextupevent = false;
mprivateflags3 &= ~pflag3_finger_down;
break;
case motionevent.action_move:
if (clickable)
// be lenient about moving outside of buttons
if (!pointinview(x, y, mtouchslop))
mprivateflags3 &= ~pflag3_finger_down;
}break;
}return true;
}return false;
}
仔細看下 case motionevent.action_down
當我們action_down事件執行的時候,clickable如果為false的話,會執行break掉**段,而直接去執行return fasle的操作。所以後面的事件就接受不到了,所以我們把這個clickable設定為true,是不是後面的事件就可以接收到了。
這個設定在xml布局裡面給b加上 android:clickable="true" 這個屬性,再跑一下程式,發現後面的action_up和action_move都被b接受到了。
如有需要,demo原始碼如下:
專案**
View的事件分發機制
view事件的分發機制由三個方法共同完成,這三個方法是 public boolean dispatchtouchevent motionevent ev public boolean onintercepttouchevent motionevent ev public boolean ontouc...
View的事件體系 事件分發機制
viewgroup事件傳遞方法 dispatchtouchevent onintercepttouchevent ontouchevent 1 dispatchtouchevent 當前view接到事件呼叫的方法,返回boolean型別值,會呼叫如下偽 邏輯,所以返回值會受自己的 ontouchev...
vscode原始碼分析 五 事件分發機制
第一篇 vscode原始碼分析 一 從原始碼執行vscode 第二篇 vscode原始碼分析 二 程式的啟動邏輯,第乙個視窗是如何建立的 第三篇 vscode原始碼分析 三 程式的啟動邏輯,效能問題的追蹤 第四篇 vscode原始碼分析 四 程式啟動的邏輯,最初建立的服務once lifecycle...