有时候会迷惑,OnTouchListener和OnClickListener究竟有什么区别。 通过源码分析一下。
一,OnTouchListener的触发逻辑
代码在View类 中
public boolean dispatchTouchEvent(MotionEvent event) {
if (mInputEventConsistencyVerifier != null) {
mInputEventConsistencyVerifier.onTouchEvent(event, 0);
}
if (onFilterTouchEventForSecurity(event)) {
//noinspection SimplifiableIfStatement
ListenerInfo li = mListenerInfo;
if (li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
&& li.mOnTouchListener.onTouch(this, event)) {
return true;
}
if (onTouchEvent(event)) {
return true;
}
}
if (mInputEventConsistencyVerifier != null) {
mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
}
return false;
}
分发touch事件时 先判断mOnTouchListener .onTouch() 是否处理了 事件,如果方法返回true(处理了),则不向下传递。
所以OnTouchListener 的触发时机是:手指一触摸就会触发。 action_down的时候就会触发。而且touchListener的字面意思"触碰监听"也比较贴切 。
二,OnClickListener的触发逻辑
代码也在View类 中
public boolean onTouchEvent(MotionEvent event) {
...
if (((viewFlags & CLICKABLE) == CLICKABLE ||
(viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
boolean prepressed = (mPrivateFlags & PREPRESSED) != 0;
if ((mPrivateFlags & PRESSED) != 0 || prepressed) {
// take focus if we don't have it already and we should in
// touch mode.
boolean focusTaken = false;
if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
focusTaken = requestFocus();
}
if (prepressed) {
// The button is being released before we actually
// showed it as pressed. Make it show the pressed
// state now (before scheduling the click) to ensure
// the user sees it.
setPressed(true);
}
if (!mHasPerformedLongPress) {
// This is a tap, so remove the longpress check
removeLongPressCallback();
// Only perform take click actions if we were in the pressed state
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)) {
performClick();//触发点
}
}
}
...
}
下面看触发点performClick()
public boolean performClick() {
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
ListenerInfo li = mListenerInfo;
if (li != null && li.mOnClickListener != null) {
playSoundEffect(SoundEffectConstants.CLICK);
li.mOnClickListener.onClick(this);//触发点击事件
return true;
}
return false;
}
在onTouch()的事件处理的逻辑中,手指抬起 action_up 时,符合click的条件,则触发mOnClickListener的逻辑。
总结:
OnTouchListener的触发点:action_down 手指按下时
OnClickListener的触发点:action_up 手指抬起时
OnTouchListener 处理逻辑在OnClickListener之前, 所以OnTouchListener 的onTouch()如果返回true, 则 onTouchEvent ()中所有逻辑失效,当然OnClickListener也不会触发。