Android事件源码分析:
Android事件传递(一):Activity、View、ViewGroup及dispatchtouchEvent、onTouchEvent梳理
Android事件传递(二):事件动作 DOWN 在Activity、View、ViewGroup传递
Android事件传递(三):事件动作 UP 在Activity、View、ViewGroup传递
偶尔看到一个问答:https://ask.csdn.net/questions/246798,为什么onTouchEvent方法会在dispatchTouchEvent方法之前执行呢?就跟了一下源码重新看了一下Android的事件传递流程
回答如下:
public class MyButton extends Button {
。。。。。省略代码。。。。。。
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.d("TTTT", "context:" + mContext + "MyButton|dispatchTouchEvent|return:" + super.dispatchTouchEvent(event) + "|event:DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.d("TTTT", "context:" + mContext + "MyButton|dispatchTouchEvent|return:" + super.dispatchTouchEvent(event) + "|event:MOVE");
break;
case MotionEvent.ACTION_UP:
Log.d("TTTT", "context:" + mContext + "MyButton|dispatchTouchEvent|return:" + super.dispatchTouchEvent(event) + "|event:UP");
break;
}
Log.d("TTTT", "========================== ");
return super.dispatchTouchEvent(event);
}
。。。。。省略代码。。。。。。
}
onTouchEvent方法会在dispatchTouchEvent方法之前执行是因为你在打印日志的时候调用了super.super.dispatchTouchEvent(event)
即在DOWN和UP打印日志的代码:
Log.d("TTTT", "context:" + mContext + "MyButton|dispatchTouchEvent|return:" + super.dispatchTouchEvent(event) + "|event:DOWN");
Log.d("TTTT", "context:" + mContext + "MyButton|dispatchTouchEvent|return:" + super.dispatchTouchEvent(event) + "|event:UP");
这时候会调用MyButton的父类View的dispatchTouchEvent方法
public boolean dispatchTouchEvent(MotionEvent event) {
// If the event should be handled by accessibility focus first.
if (event.isTargetAccessibilityFocus()) {
// We don't have focus or no virtual descendant has it, do not handle the event.
if (!isAccessibilityFocusedViewOrHost()) {
return false;
}
// We have focus and got the event, then use normal event dispatch.
event.setTargetAccessibilityFocus(false);
}
boolean result = false;
if (mInputEventConsistencyVerifier != null) {
mInputEventConsistencyVerifier.onTouchEvent(event, 0);
}
final int actionMasked = event.getActionMasked();
if (actionMasked == MotionEvent.ACTION_DOWN) {
// Defensive cleanup for new gesture
stopNestedScroll();
}
if (onFilterTouchEventForSecurity(event)) {
if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
result = true;
}
//noinspection SimplifiableIfStatement
ListenerInfo li = mListenerInfo;
if (li != null && li.mOnTouchListener != null
&& (mViewFlags & ENABLED_MASK) == ENABLED
&& li.mOnTouchListener.onTouch(this, event)) {
result = true;
}
if (!result && onTouchEvent(event)) {
result = true;
}
}
if (!result && mInputEventConsistencyVerifier != null) {
mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
}
// Clean up after nested scrolls if this is the end of a gesture;
// also cancel it if we tried an ACTION_DOWN but we didn't want the rest
// of the gesture.
if (actionMasked == MotionEvent.ACTION_UP ||
actionMasked == MotionEvent.ACTION_CANCEL ||
(actionMasked == MotionEvent.ACTION_DOWN && !result)) {
stopNestedScroll();
}
return result;
}
这个时候就调用了MyButton的onTouchEvent方法会先打印 onTouchEvent的日志
然后再打印 dispatchTouchEvent 日志,在MyButton#dispatchTouchEvent 最后又return super.dispatchTouchEvent(event);
这时又会调用MyButton的onTouchEvent再打印一次 onTouchEvent的日志
最终得日志就变成了
03-31 11:51:08.493: D/TTTT(1609): context:com.example.testtouchevent.MainActivity@528486ecMyButton|onTouchEvent|return:true|event:DOWN
03-31 11:51:08.493: D/TTTT(1609): context:com.example.testtouchevent.MainActivity@528486ecMyButton|dispatchTouchEvent|return:true|event:DOWN
03-31 11:51:08.493: D/TTTT(1609): ==========================
03-31 11:51:08.493: D/TTTT(1609): context:com.example.testtouchevent.MainActivity@528486ecMyButton|onTouchEvent|return:true|event:DOWN