Android MotionEvent事件分发
直接上图,清晰明了,图片来自这里。
触摸屏幕后产生MotionEvent
对象
疑问
onTouchEvent()
和onclick()
方法有什么关系?
假设用户点击了一个按钮,系统会调用Button所继承View类的dispatchTouchEvent()
方法。
下面是View
的部分源码,还可以看到有注册OnTouchListener
和OnClickListener
监听器的set
方法:
public class View implements ... {
...
public boolean dispatchTouchEvent(MotionEvent ev) {
if (mOnTouchListener != null
&& (mViewFlags & ENABLED_MASK) == ENABLED
&& mOnTouchListener.onTouch(this, event)) {
return true;
}
return onTouchEvent(event);
}
public void setOnTouchListener(OnTouchListener l) {
mOnTouchListener = l;
}
public void setOnClickListener(@Nullable OnClickListener l) {
if (!isClickable()) {
setClickable(true);
}
getListenerInfo().mOnClickListener = l;
}
...
}
在dispatchTouchEvent()
方法里:
-
第一个条件
mOnTouchListener
正是在setOnTouchListener
方法里赋值的,也就是说只要我们给控件注册了touch
事件,mOnTouchListener
就一定被赋值了。 -
第二个条件
(mViewFlags & ENABLED_MASK) == ENABLED
是判断当前点击的控件是否是enable
的,按钮默认都是enable
的,因此这个条件恒定为true。 -
第三个条件就是回调第一个条件里的
mOnTouchListener
的onTouch(this, event)
方法,也就是说如果我们在onTouch
方法里返回true
,就会让这三个条件全部成立,从而整个方法直接返回true
。
而我们在onTouch
方法里返回false
,就会再去执行onTouchEvent(event)
方法。
// onTouchEvent()中有个performClick()方法
public boolean performClick() {
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
if (mOnClickListener != null) {
playSoundEffect(SoundEffectConstants.CLICK);
mOnClickListener.onClick(this); <---
return true;
}
return false;
}
一切都是那么清楚了!当我们通过调用setOnClickListener
方法来给控件注册一个点击事件时,就会给mOnClickListener
赋值。然后每当控件被点击时,都会调用performClick()
方法里回调被点击控件的onClick
方法。
onTouchEvent()
先于onClick()
执行:
- 如果
onTouchEvent()
返回true
,表示事件已经被消费,则onClick()
不会执行 - 如果
onTouchEvent()
返回true
,表示事件没有被消费,则onClick()
将会执行
如需参看更多源码解析,前往: