源码分析
事件分发的类型
down,move, up,cancel
事件分发序列
down -> up
down -> move -> up
事件分发的对象
Activity ViewGroup View
事件分发的方法
dispatchTouchEvent()
onInterceptTouchEvent()
onTouchEvent()
Activity的事件分发
- dispatchTouchEvent
- PhoneWindow.superDispatchTouchEvent()
- DecorView.superDispatchTouchEvent
- ViewGroup.dispatchTouchEvent
事件由Activity到了ViewGroup,如果View没有消费掉,会调用Activity的onTouchEvent
ViewGroup的事件分发
- 事件从Down开始,接收到Down事件时会做取消并清除touch事件,置空mFistTouchTarget对象,清空Touch标记位
- 是否拦截判断(除Down时间以外),通过onIntercept,子类可以通过修改requestDisallowInteceptTouchEvent使父容器不拦截事件.默认都会走onInterceptTouchEvent方法,默认返回false
- 会调用dispatchTranseformdTouchEvent方法,内部会调用子类的dispatchTouchEvent方法或者父类的dispatchTouchEvent的方法
View中的事件处理
- 事件传递到中,会先发判断TouchListener,如果设置了TouchListener,根据回调方法onTouch方法的返回值,做响应处理,若返回true则进行第二步,否则第三步
- onTouch中返回true,则意味着事件被消费,onTouchEvent的方法将不再执行,事件结束
- onTouch中返回false,则意味着事件没有消费,将继续执行onTouchEvent方法
- onTouchEvent会更具事件类型执行不同的逻辑
- 当事件时down时,会判断是否设置了longClick事件,设置了则会更具到up的时长和longClick方法的返回值去决定是否执行onClickListener方法,修改OnLongClickListener方法的返回值可以使两个方法都执行
设计思想
架构设计思想的需求点
- 每个界面上的元素都需要有事件响应,那意味着事件的核心处理类不能太多
- 事件传递的工作不能丢给开发者,只暴露接口
- 每个控件都可以接受事件和消费事件,如果控件消费了,你那后续事件就交给这个事件了
- 如何查找会消费事件的控件
- 如何更具坐标查找该控件的范围
- 每次发生事件,都需要遍历每个子元素吗?
为什么所有的控件都继承字View
View是事件处理和传递的抽象类,还包括绘制,测量其他代码
事件分发的思考
- 容器包含很多子控件
- 子控件和容器都能消费事件
- 子控件不能进行分发给其他子控件
- 分发功能只能由容器分发给子控件
如何快速查找能响应的控件
TouchTarget消费对象的缓存队列的设计,利用链表及缓存池,通过链表操作达到复用的效果
obtain()方法,内部操作加锁,判断静态变量recycleBin缓存对象TouchTarget是否为空,不为空则取出第一个,否则new出一个TouchTarget.当一系列事件消费完后 ,释放这个对象加入缓存