1、本文的主要内容是对view的事件分发进行详细的分析,view的相对于ViewGroup来说会简单很多
1.1 在onTouchListener onTouch onClickListener 都有的情况下 在onTouchListener 返回为false 日志
09-11 08:01:47.864 6507-6507/? I/Tag: view -> onTouch ->0
09-11 08:01:47.864 6507-6507/? I/Tag: view -> onTouchEvent ->0
09-11 08:01:47.975 6507-6507/? I/Tag: view -> onTouch ->2
09-11 08:01:47.975 6507-6507/? I/Tag: view -> onTouchEvent ->2
09-11 08:01:48.088 6507-6507/? I/Tag: view -> onTouch ->1
09-11 08:01:48.088 6507-6507/? I/Tag: view -> onTouchEvent ->1
09-11 08:01:48.090 6507-6507/? I/Tag: view -> onClick
1.2 在onTouchListener onTouch onClickListener都有的情况在onTouchListener返回为true 日志
09-11 08:19:03.021 7029-7029/? I/Tag: view -> onTouch ->0
09-11 08:19:03.174 7029-7029/? I/Tag: view -> onTouch ->2
09-11 08:19:03.459 7029-7029/? I/Tag: view -> onTouch ->1
1.3 在onTouchListener onClickListener都有的情况在onTouchListener返回为true 日志
09-11 08:31:31.400 7620-7620/? I/Tag: view -> onTouch ->0
09-11 08:31:31.441 7620-7620/? I/Tag: view -> onTouch ->2
09-11 08:31:31.667 7620-7620/? I/Tag: view -> onTouch ->1
2、下面对源码进行分析
2.1 找到view的源码 dispatchTouchEvent(MotionEvent event) 这个方法 所有的view和ViewGroup的事件分发和响应都是从这里开始的可能不同的sdk版本源码有些区别 我这里是7.1.1的
以下的有出现的代码都是需要重点关注的 其他的可以不需要关注
boolean result = false 这句 这是dispatchTouchEvent返回值
ListenerInfo li = mListenerInfo;
这个ListenerInfo其实就是整个View中所有接口存放的位置
最重要的两个方法之一
if (li != null && li.mOnTouchListener != null
&& (mViewFlags & ENABLED_MASK) == ENABLED
&& li.mOnTouchListener.onTouch(this, event)) {
result = true;
}
这里li已经赋值了不可能等于空
mOnTouchListener 这个方法就是你是否实现了接口 这边我们也不为空
(mViewFlags & ENABLED_MASK) == ENABLED 这个是你的view是否可用 也就是可不可以点击
一般默认都是为可用 这里也是 true
li.mOnTouchListener.onTouch(this, event) 这个方法就是实现的方法
为什么onTouch是第一个调用也是这个原因 这里在1.1的情形中是返回false
所以 result = true;这个if判断不会进来
if (!result && onTouchEvent(event)) {
result = true;
}
因为上面 if判断没进去 result 还是 false onTouchEvent(event)这里就调用了onTouchEvent 的方法
现在走到onTouchEvent内部看看 在这里面如果默认返回super.onTouchEvent(event) 这里都是返回true
在这个方法里会看到一个方法叫performClick() 这个就是点击事件 我们进到里面看看
if (!post(mPerformClick)) {
performClick();
}
......
public boolean performClick() {
final boolean result;
final ListenerInfo li = mListenerInfo;
if (li != null && li.mOnClickListener != null) {
playSoundEffect(SoundEffectConstants.CLICK);
li.mOnClickListener.onClick(this);//这里就是onClick最后走的原因
result = true;
} else {
result = false;
}
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
return result;
}