从源码来看,OnTouchEvent是View的一个方法,处理MotionEvent封装的事件,而OnTouchListener是View内部静态类ListenerInfo的一个实例变量,ListenerInfo封装了一个View各种事件监听器。如图:
当ACTION_DOWN事件传递给View时,此时先调用View的dispatchTouchEvent,我们看看dispatchTouchEvent 的源码
/**
* Pass the touch screen motion event down to the target view, or this
* view if it is the target.
*
* @param event The motion event to be dispatched.
* @return True if the event was handled by the view, false otherwise.
*/
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 (onFilterTouchEventForSecurity(event)) {
//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;
}
}
...
return result;
}
这里我们只看对于返回值有影响的方法,即代码中result值的变化。默认result为false,下面就是几个if语句,这里的mListenerInfo 就是ListenerInfo 的对象,View唯一的ListenerInfo 的实例,当用户设置setOnTouchListener监听器时,如下
/**
* Register a callback to be invoked when a touch event is sent to this view.
* @param l the touch listener to attach to this view
*/
public void setOnTouchListener(OnTouchListener l) {
getListenerInfo().mOnTouchListener = l;
}
getListenerInfo 就生成了mListenerInfo,这里就设置了mListenerInfo的一个成员变量mOnTouchListener 为 l 。回到if语句来,li.mOnTouchListener.onTouch(this, event) 这句话就在执行用户设置的setOnTouchListener的回调,它的结果返回true,消费此次事件,result = true 那么将不会执行下面 onTouchEvent(event)方法;如果它的结果返回false,那么继续执行onTouchEvent(event)方法。最终根据result值,如果dispatchTouchEvent返回true 代表 view消费了此事件,如果返回false就代表不做处理,这里的result值也传给了ViewGroup中负责子View之间转移事件的方法,遍历所有子View,得出在ViewGroup的onInterceptTouchEvent默认返回false 的前提下,它的dispatchTouchEvent方法返回值。
总结:用户不设置OnTouchListener,系统是默认执行onTouchEvent(event)方法,如果设置了OnTouchListener,那么就会先执行它,根据OnTouchListener的返回值再决定是否执行onTouchEvent(event)。看来OnTouchListener的优先级比onTouchEvent要高。