onTouch和onClick
- 设置view的监听
myView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.e(tag, "onClick");
}
});
myView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
Log.e(tag,"onTouch");
return false;
}
});
点击view打印log如下:
01-19 05:04:02.188 5013-5013/com.list E/MainActivity: onTouch
01-19 05:04:02.255 5013-5013/com.list E/MainActivity: onTouch
01-19 05:04:02.256 5013-5013/com.list E/MainActivity: onClick
可以知道先执行的onTouch事件 然后执行onClick事件
- 如果将onTouch返回true
01-19 05:13:08.183 5661-5661/com.list E/MainActivity: onTouch
01-19 05:13:08.228 5661-5661/com.list E/MainActivity: onTouch
结果只执行了onTouch未执行onClick
- 每次事件都会首先调用dispatchTouchEvent 看一下主要的代码
public boolean dispatchTouchEvent(MotionEvent event) {
// If the event should be handled by accessibility focus first.
...
boolean result = false;
...
if (onFilterTouchEventForSecurity(event)) {
if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
result = true;
}
//noinspection SimplifiableIfStatement
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;
}
}
if (!result && mInputEventConsistencyVerifier != null) {
mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
}
// Clean up after nested scrolls if this is the end of a gesture;
// also cancel it if we tried an ACTION_DOWN but we didn't want the rest
// of the gesture.
if (actionMasked == MotionEvent.ACTION_UP ||
actionMasked == MotionEvent.ACTION_CANCEL ||
(actionMasked == MotionEvent.ACTION_DOWN && !result)) {
stopNestedScroll();
}
return result;
}
方法内第一行写到 // If the event should be handled by accessibility focus first.
意思就是每次事件发生都会先走此方法。
方法内定义了 result 变量来判断事件是否需要拦截默认是false
接下来
ListenerInfo li = mListenerInfo;
if (li != null && li.mOnTouchListener != null
&& (mViewFlags & ENABLED_MASK) == ENABLED
&& li.mOnTouchListener.onTouch(this, event)) {
result = true;
}
li 是我们在setOnTouchListener的时候赋值
public void setOnTouchListener(OnTouchListener l) {
getListenerInfo().mOnTouchListener = l;
}
当我们return true的时候
li.mOnTouchListener.onTouch(this, event) = true
result赋值为true , 接下来下面的代码if条件不成立 onTouchEvent就不会被调用
if (!result && onTouchEvent(event)) {
result = true;
}
如果我们return false的时候将会走到onTouchEvent方法
if (mPerformClick == null) {
mPerformClick = new PerformClick();
}
if (!post(mPerformClick)) {
performClick();
}
当case MotionEvent.ACTION_UP:的时候会调用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;
}
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
notifyEnterOrExitForAutoFillIfNeeded(true);
return result;
}
在performClick()中调用了 li.mOnClickListener.onClick(this);回调到我们设置的onClickListener方法;
然后返回result;
然后上面if判断的方法
if (!result && onTouchEvent(event)) {
result = true;
}
重新将result设置为true接下来的方法将不会执行 到最后返回result。
所以onTouch优先于onClick