源码分析
我们知道view的事件分发总是从dispatchTouchEvent
方法开始,我们就来分析dispatchTouchEvent
对应的源码执行逻辑:
public boolean dispatchTouchEvent(MotionEvent event) {
...
boolean result = false;
...
if (onFilterTouchEventForSecurity(event)) {
if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
result = true;
}
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;
}
重点分析这段代码:
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;
}
其中ListenerInfo:
将View点击事件抽象成class,包含OnClickListener/OnFocusChangeListener/OnScrollChangeListener等等事件;
可以得出如下结论:
- 当View的
enable【view使能】
为true时,会先执行OnTouchListener.onTouch
事件,如果OnTouchListener.onTouch
为true,则onTouchEvent事件
不会执行,反之会执行onTouchEvent(event)事件
那OnClickListener事件
在哪里执行的呢?我们看下onTouchEvent(event)
方法这段源码:
switch (action) {
case MotionEvent.ACTION_UP:
...
if (!focusTaken) {
// Use a Runnable and post this rather than calling
// performClick directly. This lets other visual state
// of the view update before click actions start.
if (mPerformClick == null) {
mPerformClick = new PerformClick();
}
if (!post(mPerformClick)) {
performClickInternal();
}
}
}
...
break;
其中 performClickInternal()方法如下:
private boolean performClickInternal() {
notifyAutofillManagerOnClick();
return performClick();
}
performClick()方法如下:
public boolean performClick() {
...
final boolean result;
final ListenerInfo li = mListenerInfo;
if (li != null && li.mOnClickListener != null) {
playSoundEffect(SoundEffectConstants.CLICK);
li.mOnClickListener.onClick(this);
result = true;
} else {
result = false;
}
return result;
}
li.mOnClickListener.onClick(this)
正是对应的OnClickListener事件
回调。
这一段代码可以得出如下结论:
OnClickListener事件
执行的前提是onTouchEvent(event)
方法执行了MotionEvent.ACTION_UP
事件。
总结
- 当
onTouchListener
返回false
时,执行顺序为onTouchListener
->onTouchEvent
->onClickListener
; - 当
onTouchListener
返回true
时,只为执行onTouchListener
; onClickListener
执行的前提是执行了onTouchEvent
且能执行MotionEvent.ACTION_UP
事件。