OnTouchListener、onTouchEvent、OnLongClickListener、OnClickListener的优先级
1、看下view的dispatchTouchEvent源码:
public boolean dispatchTouchEvent(MotionEvent event) {
//...
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;
}
可以非常清楚看到,先执行的是onTouchListener的onTouch方法,如果返回true则代表事件被消费掉,则不会往下走到onTouchEvent中;
相反,如果没有消费则才往下走到onTouchEvent中。
2、接着看view的onTouchEvent方法:
可以很清楚看到,如果程序注册了onClickListener,则会执行onClickListener的onClick方法
总结如下:
1.view在执行dispatchTouchEvent的时候先要去判断该view是否有touchListener和执行TouchListener的onTouch方法的返回值。
2.TouchListener的onTouch方法返回false,事件继续传递在dispatch方法中调用了同级的onTouchEvent方法
3.然后在onTouchEvent方法中的UP事件中判断是否注册有onClickListener,有就执行onclick方法。
OnTouchListener --> onTouchEvent --> OnLongClickListener/OnClickListener
OnTouchListener是执行在onTouchEvent之前的,OnTouchListener优先级高于onTouchEvent,就是如果事件能传递到onTouchEvent中那么事件之前一定传递到了OnTouchListener中(当然如果像前面讲到的那种情况onTouchEvent中对ACTION_DOWN返回了false, 那后续的ACTION_UP等事件也就不会传到OnTouchListener和onTouchEvent中了)。如果在OnTouchListener的onTouch函数中返回了true,则代表消费了该事件,该事件也不会传到onTouchEvent中了。
而OnClickListener和OnLongClickListener都是在onTouchEvent中进行处理判断的,在onTouchEvent中返回true处理触摸事件才能判断该触摸事件是不是点击,如果在onTouchEvent返回false不处理触摸事件,则这时的OnClickListener和OnLongClickListener都是无效的。那OnClickListener和OnLongClickListener的区别就是OnLongClickListener在onTouchEvent判断到是ACTION_DOWN事件并且按压持续一定时间后就会触发OnLongClickListener;但之后要等到onTouchEvent判断到是ACTION_UP事件时才会触发OnClickListener,所以OnLongClickListener优先级要大于OnClickListener,当然如果在OnLongClickListener的onLongClick函数中返回true的话就不会触发后面的OnClickListener了。
事件分发实验:
https://www.cnblogs.com/fuly550871915/p/4983682.html
参考郭霖的事件分发机制解析:https://blog.csdn.net/guolin_blog/article/details/9097463