安卓自定义View进阶-事件分发机制原理
http://www.gcssloop.com/customview/dispatch-touchevent-theory
这篇博客不错,每次遇见事件分发时,都会看一遍
view事件分发
1.android对事件的定义
点击,滑动,长按等,每个事件都由ACTION_DOWN/ACTION_MOVE...ACTION_MOVE/ACTION_UP组成
2.view事件分发
主要分为两个阶段
1.第一部分:WMS服务起来的时候会开启一个事件监听线程,捕获屏幕上各种点击滑动事件,通过层层分发,分发给当前activity.这一段的事件分发是由WMS来处理。
2.第二部分:事件到Activity后,会在Activity/ViewGroup/View中传递,直到被消费。整个传递过程就是一个责任链模式。
3.事件在Activity/ViewGroup/View具体分析
事件处理是从Activity开始传递经过ViewGroup最终到view,整个过程如果没有被消费,又会从view传递到viewgroup再到Activity.整个过程是一个U型图
主要函数:
事件分发由以下函数协作:
dispatchTouchEvent:三者都有的方法,负责事件的分发和消费
onInterceptTouchEvent:viewgroup特有的方法,在dispatchTouchEvent中调用
onTouchEvent:三者均有的方法,在dispatchTouchEvent中调用
Activity:事件传递到Activtiy,activty分发给phonevindow,再分发给DecoView,到此传递给ViewGroup
ViewGroup:事件传递给ViewGroup,判断是否拦截,如果拦截,事件停止传递,不拦截,遍历所有子view,找到承受点击事件的子view,事件传递到子view上
View:事件传递给view ,按照onTouch() ->> onTouchEvent() ->> performClick() ->> onClick()处理事件
如果子view中重写dispatchTouchEvent,返回false,则事件不会再传递给子view了,相当于没有子view了,子view不处理事件了。
view处理相关:
在子view的dispatchTouchEvent中按照顺序调用以下函数
onTouch:当把手放到View上后,onTouch方法被一遍一遍的调用
onTouchEvent:最终调用onClick
onClick:点击回调事件
4.事件争夺处理,子view和父view
4.1子view如何阻止父view拦截事件
请求父控件不拦截子空间的触摸事件,自定义重写子view的dispatchTouchEvent()方法:
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
getParent().requestDisallowInterceptTouchEvent(true);
return super.dispatchTouchEvent(ev);
}
4.2父view怎么判断当前遍历的View是不是正在点击的View:通过比较点击事件的坐标和子view的位置
4.3滑动冲突
滑动冲突的解决思路是:事件到底给谁,到底让谁消费