与事件分发相关的几个事件:
1、Touch事件;
2、onLongClickListener事件;
3、onClickListener事件;
首先概述一下几个事件触发的时机:
1、Touch事件发生在MoutionEvent的Down事件期间,move事件之前;onLongClickListener也是发生在Down事件之行,move事件之前;onClickListener事件发生在MoutionEvent的Up事件期间;
2、Touch事件的优先级高于onClickListener事件;
3、Down事件期间,系统会根据press的时间,来判断是否触发onLongClickListener事件;如果触发,则会在 onLongClickListener事件 返回true时会设置mHasPerformedLongPress字段值为true,然后再up事件时,判断mHasPerformedLongPress,为false才会执行performClickInternal,也就是onLongClickListener返回false才会执行onClickListener;
4、相对于第3点,Touch事件不需要这个“press的时间”的判断,一旦View感知到有Touch事件发生,就会立即执行;
下面我们再来说说View的事件分发。
View的事件分发分两部分,一个是View的事件分发,另一个是ViewGroup的事件分发。二者稍有区别。下面先说View的事件分发。
View的事件分发
对View而言,在其dispatchTouchEvent()方法中,如果监听到我们设置了setTouchListener()监听,并在onTouch()方法中返回了true,那么表示我们优先执行Touch事件,并拦截Click事件。如果我们没有设置setTouchListener()监听或者设置了监听,但在onTouch()方法中返回了false,则表示我们不拦截Click事件。
然后,在dispatchTouchEvent()方法中,会调用onTouchEvent()方法来判断是否执行事件分发,如果onTouchEvent()方法返回false,则会在“MotionEvent.ACTION_UP”中,执行performClickInternal()方法,该方法内部,则是调用performClick()方法,而performClick()方法则会去执行 mOnClickListener.onClick(this) 的回调;
ViewGroup的事件分发
对ViewGroup而言,在其dispatchTouchEvent()方法中,会调用onInterceptTouchEvent(MotionEvent ev)方法来判断当前ViewGroup是否需要拦截该事件。
在onInterceptTouchEvent(MotionEvent ev)方法中,如果返回true,则表示本次事件不下发,由本级ViewGroup自己消费调。如果返回的是false,则表示当前ViewGroup不拦截本次事件,本次事件继续向下分发给下级子View去处理,如果下级子View还是ViewGroup类型, 则采用“递归”的形式循环遍历下级子View,并下发事件,直到找到处理该事件的View为止。
如果在整个下发的过程中,最终都没有找到要消费处理该事件的子View,那么该事件就沿着原路线返回给根View去处理消费。