View的事件分发机制总结

事件分发机制是指系统对用户手指接触屏幕时所产生的一系列MotionEvent对象在View的层级中如何传递所制定的机制。

1.MotionEvent

MotionEvent是一个类,Android将输入事件都生成了 MotionEvent对象。主要有这几种事件类型:

类型说明
ACTION_DOWN代表手指刚接触屏幕
ACTION_MOVE代表手指在屏幕上移动
ACTION_UP代表手指刚从屏幕松开
ACTION_CANCEL代表事件序列结束(一般为父view拦截事件)

 

 

 

 

 

 

还有一些与多指触碰有关的这里不展开讨论。

 

2.事件序列

 从手指触摸到屏幕开始直到手指离开屏幕所产生的​一系列事件叫做同一事件序列。一个完整的事件序列,一般是以DOWNk开始,以UP结束,当然也有以CANCEL结束的,中间可能有多个MOVE。当一个View处理某个事件时,这个事件序列的后序事件都会直接传给此view。

3.分发流程

   与分发过程有关的3个方法:

   ①dispatchTouchEvent(MotionEvent ev) ——进行事件分发

   ②onInterceptTouchEvent(MotionEvent ev)——进行事件拦截,viewGroup才拥有此方法,在dispatchTouchEvent()方法中调用

   ③onTouchEvent(MotionEvent ev)——进行点击事件处理,在dispatchTouchEvent()方法中调用

 分发过程:

    1.当事件产生时,首先传递给activity,我们知道activity加载时先添加phoneWindow,phoneWindow又会添加DecorView,所以DecorView为activity的根view,事件处理工作最后交给DecorView,而DecorView又将事件处理交给根viewGroup,调用根vewGroup的dispatchTouchEvent方法。

    2.在此方法中,首先判断事件是否为down事件,是的话进行一些初始化工作(将上次事件序列的状态清空)。接着进行一个判断语句,如果事件为down事件或者mFirstTouchTarget不为空,则进行if语句,否则直接将拦截标志位设为true,表示viewGroup拦截此事件。mFirstTouchTarget表示的是上个事件的处理者,如果为空则表示没有处理者。所以这个判断语句表示如果是down事件,是一个事件序列的开始,应该询问子view是否处理,如果是其他事件并且mFirstTouchTarget为空,没人处理上个事件,则子view中没人处理,由viewGroup直接拦截处理。

   3.在判断语句中,先得到disallowIntercept的值,这个标志位表示子view是否允许父view拦截除down之外事件,子view可通过调用requestDisallowInterceptTouchEvent来设置。为false的话表示不允许,直接将拦截标志位设为false。为true的话,表示允许,将调用viewGroup的onInterceptTouchEvent(),根据此方法的返回值设置拦截标志位,默认为false,有需要时需重写此方法。

  4.如果viewGroup不拦截事件,则需遍历子view,判断子view是否能够接收事件,如能接收则交给子view。遍历子view为倒序遍历,则从最上层子view开始,判断条件为触摸点位置是否在子view范围内,或者子view是否在播放动画,均不符合则遍历下一个。最终如果由子view符合条件则调用子view的dispatchTouchEvent()方法,没有的话则调用super.dispatchTouchEvent()方法。viewGroup继承于View,所以调用的是View的dispatchTouchEvent方法。

  5.在View的dispatchTouchEvent()方法中,如果onTouchListener不为空并且onTouch()方法返回true则表示事件被消费,不会再执行onTouchEvent()方法。在onTouchEvent()方法中,只要View的CLICKABLE和LONG_CLICKABLE有一个为true,那么OnTouchEvent()方法就会返回true消费此事件。如果View设置了点击事件OnClickListener,那么就会执行onClick方法。如果子view的dispatchTouchEvent()方法返回false,则会调用父view的onTouchEvent()方法。

    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值