Android事件分发(1)

由于遇到了ScrollView嵌套EditText的滑动冲突问题,想深入了解一下Android的事件分发机制到底是怎么回事,也做一个总结。
参考了部分郭霖的源码分析 Android事件分发机制完全解析,带你从源码的角度彻底理解

一、需要先理解两件事情

  1. 安卓事件事件分发主要用到了三个函数:

    • dispatchTouchEvent(MotionEvent ev)
    • onInterceptTouchEvent(MotionEvent ev)
    • onTouchEvent(MotionEvent event)
  2. 可以看到三个函数的参数都是MotionEvent 类型的参数。
    当用户进行点击,滑动,长按等操作的时候,会产生一系列的触屏事件。
    这里需要理解的事情是:触屏事件是被当成了MotionEvent 对象在进行分发和处理的

  3. MotionEvent 对象简单来说定义了一些基础事件:
    ACTION_DOWN:按下控件,代码0
    ACTION_UP:手离开控件,代码1
    ACTION_MOVE:手指移动,代码2
    ACTION_CANCEL:触摸事件被取消了,代码3

还有其他,不列举了。

二、onTouch和onTouchEvent区别

看一下源码中的逻辑:

public boolean dispatchTouchEvent(MotionEvent event){  
    ... ...  
    if(onFilterTouchEventForSecurity(event)){  
        ListenerInfo li = mListenerInfo;  
        if(li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED  
            && li.mOnTouchListener.onTouch(this, event)) {  
            return true;  
        }  
        if(!result && onTouchEvent(event)){  
            return true;  
        }  
    }  
    ... ...  
    return false;  
}  

onTouch的执行:
if(li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
&& li.mOnTouchListener.onTouch(this, event))一共有四个判断。
li != null 的判断一般都为真(源码中mListenerInfo赋值给了li,mListenerInfo在getListenerInfo()中赋值,getListenerInfo()在多个地方调用)
其次,li.mOnTouchListener是通过setOnTouchListener赋值的,如果设置了OnTouchListener,值为true
第三,(mViewFlags & ENABLED_MASK) == ENABLED 是判断控件是否是enable的,
第四,li.mOnTouchListener.onTouch(this, event)执行了 setOnTouchListener所设置的onTouch
然后可以看到onTouchEvent的执行:
if(!result && onTouchEvent(event))
A.假如result为true的话,!result 为false,判断到这里,if已经不成立了,所以onTouchEvent(event)没有执行
B.假如result为false的话,!result 为true,会执行onTouchEvent(event)

所以可以得出以下结论:
1. View在分发事件(dispatchTouchEvent中)的时候,优先对onTouch要不要执行进行了判断。
2. 如果 onTouch执行后,返回了true,触摸事件被消费,onTouchEvent(event)也就不再执行了。
3. View的源码中,只有setOnTouchListener对onTouch事件进行了赋值。onTouch是我们自己赋值进去的,几乎没做什么操作。
由此可以得出了几个个结论:、一是点击事件,滑动,长按等等事件的判断和实现,不是在onTouch中实现的,是在onTouchEvent(event)中实现的,因为onTouch事件默认是null的
二是,onTouch事件默认是null的,对于onTouch的赋值,是给用户提供了一个拦截onTouchEvent(event)的机会,联想到上一篇 ScrollView嵌套EditText的滑动冲突问题 ,解决问题的关键也是在 onTouchEvent发生之前,做了一些处理。

猜你喜欢

转载自blog.csdn.net/kangyouv/article/details/76408414