点击事件有三个重要的方法它们分别是:
- dispatchTouchEvent(MotionEvent ev):用来进行事件的分发
- onInterceptTouchEvent(MotionEvent ev):用来进行事件的拦截,在dispatchTouchEvent()中调用,需要注意的是View没有提供该方法
- onTouchEvent(MotionEvent ev):用来处理点击事件,在dispatchTouchEvent()方法中进行调用
由ViewGroup开始
class ViewGroup : View() {
private val children = arrayOf<View>()
override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
var result = onInterceptTouchEvent(ev)
if (!result){
for (child in children){
dispatchTransformedTouchEvent(ev , child)
}
}
return result
}
open fun onInterceptTouchEvent(ev: MotionEvent?):Boolean{
return false
}
private fun dispatchTransformedTouchEvent(event : MotionEvent? , child : View?): Boolean {
return if (child == null) {
super.dispatchTouchEvent(event)
} else {
child.dispatchTouchEvent(event)
}
}
}
open class View {
open fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
var result = false
val li: ListenerInfo = mListenerInfo
if (li != null
&& li.mOnTouchListener != null
&& mViewFlags and ENABLED_MASK === ENABLED
&& li.mOnTouchListener.onTouch(this, event)
) {
result = true
}
if (!result && onTouchEvent(event)) {
result = true;
}
return result
}
open fun onTouchEvent(ev: MotionEvent?): Boolean {
if (mTouchDelegate != null) {
if (mTouchDelegate.onTouchEvent(event)) {
return true
}
}
val clickable = CLICKABLE || LONG_CLICKABLE
return if (clickable) {
when (ev?.action) {
MotionEvent.ACTION_UP -> {
performClick()
}
}
true
} else {
false
}
}
fun performClick(): Boolean {
val li = mListenerInfo;
val result = if (li != null && li.mOnClickListener != null) {
li.mOnClickListener.onClick(this);
true;
} else {
false;
}
return result;
}
}
参考了刘望舒大佬的文章Android View体系(五)从源码解析View的事件分发机制 | BATcoder - 刘望舒