一、方法的介绍:
onTouch: 该方法是onTouchListener的回调方法,在View的dispatchTouchEvent()方法中调用;
onTouchEvent:View的内部方法,在dispatchTouchEvent()方法中调用;
onClick:该方法是onClickListener的回调方法,在onTouchEvent中调。
方法执行的先后顺序: onTouch -> onTouchEvent -> onClick。
下面讲述,以上顺序如何得知。
二. View的dispatchTouchEvent方法分析
View的dispatchTouchEvent代码:
public boolean dispatchTouchEvent(MotionEvent event) {
if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&mOnTouchListener.onTouch(this, event)) {
return true;
}
return onTouchEvent(event);
}
当一个事件传递到View时,会首先执行dispatchTouchEvent()方法。此时,先进入一个判断,三个条件同时满足,则返回true,不走onTouchEvent()方法;否则返回Touch Event方法的执行结果。
条件一:onTouchListener是否为空,看程序员是否set了onTouchListener;
条件二:该View是否enable(控件基本默认enable);
条件三:onTouch方法的返回值。
所以,先走了onTouch方法。如条件一二都满足,在onTouch中返回false,则会走onTouchEvent方法。
所以,再走onTouchEvent方法。onTouchEvenr方法中在ACTION_UP的事件下,执行了performClick方法,该方法如下:
public boolean performClick() {
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
if (mOnClickListener != null) {
playSoundEffect(SoundEffectConstants.CLICK);
mOnClickListener.onClick(this);
return true;
}
return false;
}
不难解读,当onClickListener不为空时,调用了onClick方法。
所以,最后走onClick方法。
且onClick方法是在手指抬起来的时候去调用的。
三.只有当dispatchTouchEvent方法在前一个Action返回true,后一个Action才会执行。
如何解读这句话???
例如:
1.若ACTION_DOWN事件返回false,此时dispatchTouchEvent方法直接返回true。那么肯定可以接收到后面的MOVE或者UP事件;
2.若ACTION_DOWN事件返回true,此时dispatchTouchEvent方法走onTouchEvent方法,而该方法中的逻辑是只要该View是可点击,均返回true。所以dispatchTouchEvent方法还是返回true,还是可以接收到后面的MOVE或者UP事件。
所以:这就解释了一个问题,为什么TextView或者ImageView在onTouch方法中,如果在ACTION_DOWN是返回了false,就无法接收到其他事件MOVE或者UP的原因。
解决办法就是将View设置为可点击:setClickable(true);