首先看一下中重要的源码
public boolean dispatchTouchEvent(MotionEvent event) {
......
boolean result = false;
......
//过滤onTouchEvent事件是否安全,正常流程都会返回 true
if (onFilterTouchEventForSecurity(event)) {
......
//首先判断是否设置了onTouchListener,如果设置了首先执行onTouch方法
//ListenerInfo是在我们设置setOnTouchListener时初始化的
//可以看下setOnTouchListener,其中的getListenerInfo是单例模式
ListenerInfo li = mListenerInfo;
if (li != null && li.mOnTouchListener != null//已经设置了不会空
&& (mViewFlags & ENABLED_MASK) == ENABLED//判断按钮是否能够点击
&& li.mOnTouchListener.onTouch(this, event)) {
result = true;//result和 onTouch 的返回值保持一致
}
//只有onTouch方法返回为 false 的情况下才会去执行 onTouchEvent
//onTouchEvent中会去执行 onClick 方法
if (!result && onTouchEvent(event)) {
result = true;
}
}
......
return result;
}从上面的代码可以看出 onTouchListener 的优先级高于 onTouchEvent,只有当 onTouch 方法
返回为 false 的情况下才会去执行 onTouchEvent,再来看一下 onTouchEvent 的部分重要源码
public boolean onTouchEvent(MotionEvent event) {
final float x = event.getX();
final float y = event.getY();
final int viewFlags = mViewFlags;
final int action = event.getAction();
......
if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
switch (action) {
//会在ACTION_UP事件中处理onClick
//也就是在我们手指松手的那一刻才会去执行 onClick 方法
case MotionEvent.ACTION_UP:
mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
if ((viewFlags & TOOLTIP) == TOOLTIP) {
handleTooltipUp();
}
......
if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
......
if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
// 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)) {
//该方法最终会去执行 onClick 方法
performClickInternal();
}
}
}
......
mIgnoreNextUpEvent = false;
break;private boolean performClickInternal() {
......
return performClick();
}
public boolean performClick() {
......
final boolean result;
final ListenerInfo li = mListenerInfo;
//关键代码,判断是否设置了onClickListener,这块和onTouch时类似
if (li != null && li.mOnClickListener != null) {
playSoundEffect(SoundEffectConstants.CLICK);
li.mOnClickListener.onClick(this);
result = true;
} else {
result = false;
}
......
return result;//最终返回执行结果
}
下面来一张onTouch方法和onClick方法执行的流程图
源码相关应用:
场景:通过以上源码的分析,我们知道如果一个View同时设置了onTouchListener和
onClickListener,此时要想onClick得到执行我们必须在onTouch方法中手动返回false
如果业务需求我们即要onTouch方法最终返回true,同时又要onClick得到执行
根据上边的源码我们可以在onTouch方法中手动执行 v.performClick
好,这篇学习笔记结束啦