觸控事件分發機制的例項分析 二

2021-09-24 23:52:12 字數 3398 閱讀 7252

在網上搜到了很有意思的一道題,仔細想一下這道題。

答案是如果有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...