以下分析仅仅是对源码的分析,当然,如果是自定义了事件的分发,那么就需要另外讨论了。
- 正常触发一个View的事件流程是什么?
- 当触发屏幕的触摸事件的时候,首先通过Activity分发事件,交给PhoneWindow分发事件,接着交给DecorView分发事件,紧接着就调用了ViewGroup( DecorView 父类方法)的分发事件,然后通过dispatchTransformedTouchEvent来给子View分发事件,最终交个View的分发事件,然后就是事件的处理了onTouchEvent。
- Activity的分发事件是从哪里传递过来的?
- 事件分发的触发条件是什么?
- 也就是在触摸按下的时候就进行事件分发了,直到触摸取消或者抬起为一个事件分发周期
- 如何拦截Activity的触摸事件?
- dispatchTouchEvent返回true,如果需要处理事件在子视图中的分发需要super.dispatchTouchEvent或者自定义事件分发
- 原因:在Activity的dispatchTouchEvent中,onTouchEvent的触发条件是,子视图的dispatchTouchEvent返回false
- onTouchEvent始终返回true
- 原因:通过View.dispatchTouchEvent可以在得知,如果满足onTouchEvent返回true,那么就能保证View.dispatchTouchEvent可以返回true,这个时候就能达到屏蔽Activity的onTouchEvent了
- dispatchTouchEvent的作用?
- 负责当前VIew的事件分发操作 例如接下来的事件拦截事件处理,这些都是系统默认写好的
- 表明当前View的事件消费状态
- 返回值含义:应用层代表事件是否允许交给Activity消费
- 场景:例如一个视图A接受触摸事件,默认情况下,Activity也是可以收到事件的,如果不想让Activity也接收到事件,那么就将这个值设置为true
- onInterceptTouchEvent的作用?
- 其返回值决定了是否拦截事件向子视图的分发,也就是触发子视图的事件分发方法
- true:代表不想下分发,自己处理事件 例如:当触发屏幕某个位置时候,不像让当前位置的子视图接收到事件
- false:代表向下分发,自己不接受事件
- onTouchEvent的作用?
- 处理触摸事件的响应方式 例如:操作视图平移 缩放等一系列操作
- onTouchEvent的返回值有什么作用?
- 决定了View.dispatchTouchEvent的返回值状态,也间接影响了事件的最终消费对象
- requestDisallowInterceptTouchEvent的作用?
- 决定onInterceptTouchEvent是否执行 参数:true执行 false不执行
- 为什么重写子视图的super.onTouchEvent(event)/ 返回false的时候,在移动时候父视图的onInterceptTouchEvent就不会执行?
- super.onTouchEvent(event)默认情况下返回的本身就是false
- 首先:满足onInterceptTouchEvent执行的条件是按下事件 第一次触摸目标mFirstTouchTarget不为空 允许拦截事件标识,
- 其次:第一个条件是不满足的排除,而第二个不为空的触发是addTouchTarget,因为onTouchEvent返回了false,经过一系列的传递dispatchTransformedTouchEvent也返回了false,这个时候就不能触发addTouchTarget也就是说mFirstTouchTarget =null,所以就不能执行了onInterceptTouchEvent,默认情况下disallowIntercept = false。
- 默认情况下:如何实现父类不拦截,让子类处理onTouchEvent?
- 首先:让子视图的onTouchEvent返回true,但是这种情况下父视图的onInterceptTouchEvent会执行一次,如果这里没有方法其实也没什么,如果也做了处理,那么就还需要再次处理,根据问题9可以知道以下解决方案。
- 其次:通过down的时候通过parent.requestDisallowInterceptTouchEvent(true)在抬起或者取消的时候parent.requestDisallowInterceptTouchEvent(false)
- 另一种方法:在dispatchTouchEvent中super.dispatchTouchEvent之后进按下时候行parent.requestDisallowInterceptTouchEvent(true)就可以达到父类不拦截事件
- 为什么重写DispatchTouchEvent直接返回true/false都不能分发事件?
- 事件分发的目的是为了交给指定的View通过onTouchEvent进行事件消费处理。而如果直接返回true/false,其过程并没有对onInterceptTouchEvent和onTouchEvent进行处理,所以也就不能进行事件分发处理了。
- 而返回值的意义是 :获取当前View的事件消费状态 最终决定Activity是否消费事件 比如都不消费就交给Activity的onTouchEvent是否处理
- 为什么要在super.dispatchTouchEvent之后进行请求父类是否拦截?
- 因为:在super.dispatchTouchEvent中,每次的DOWN事件都会重新将拦截事件标识改为拦截事件,因此在这个方法之后的DOWN重新设置为不拦截,那么之后的MOVE等事件就能达到不拦截的目的