在Android中主要存在两种事件,一种是按键事件,对应物理按键或者虚拟按键,一种是触摸屏事件。本文主要了解触摸消息的传递过程,以及可以对消息做什么处理。是验证性质分析!
对于所有的消息处理,底层的东东,应用工程师不太关心,不过要大致知道是什么情况,其总的过程如下所示。
在具体的调用过程中,涉及到了几个具体的函数,是需要弄清楚的。
1.dispatchTouchEvent(MotionEvent ev) 这个只有在Acitity和ViewGroup中才有,View是没有这样的函数。这个函数会进行消息派发。
2.onIntercepTouchEvent(MotionEvent ev)这个只有在ViewGroup才有用,它提供一种能力,能够截断消息的派发,后面会说到截断的效果。
如果返回True则进行截断。如果它有子控件调用了requestDisallowInterceptTouchEvent(),这个方法是不会调用的。
3.onTouchEvent(),这个函数Activity,ViewGroup ,View 都可以进行重载。经常有一种说法,就是这个函数如果返回True,则代表这个函数可以消费了这个事 件,所谓的消费了这个事件,就是指定当前的View是这个消息处理过程中的目标。
为了查看具体的情况,写了一个小的Demo.其视图如下所示:
通过做试验,得出了下图:
以上消息拿Activity对应的窗口进行举例(不包含对话框和popupWindow等)
触摸的消息从动作DOWN开始,UP或者CANCEL结束,中间一般可以有MOVE等操作。
消息分为两部分。DOWN消息和其它消息。
DOWN消息有些特殊,在DOWN消息派发的过程中,要定位这次消息流程目标是哪个控件,也就是找到谁的OnTouchEvent返回是True。
如果所有的onTouchEvent都返回false,最终的消息目标是activity中的onTouchEvent();上图中黑色实线所应对就是这种情况下DOWN消息的派发过程。
为什么反复的强调一次完成消息派发过程中的目标。因为非DOWN消息和DOWN不一样的。
DEMO中可以试试。
DOWN 消息派发过程:
结论一:消息的派发自顶向下,由根树图开始(如果是Activity对应就是DecorView,如果是对话框等就是其最外层的ViewGroup,流动像一个U形
结论二:如果onInterceptTouchEvent()返回了True,并且该控件允许截断,则消息不会往下流动,直接调用本层的OnTouchEvent();
结论三:如果在消息派发的路线上,有onTouchEvetn()返回True,其上层控件的onTouchEvent()都不会调用。假定MyViewGroup返回True
非DOWN消息派发过程:
结论一:与DOWN消息派发不同,如果当前控件就是这次消息目标,其下层的控件的消息相关都不会派发(只有目标控件的OnTouchEvent会调用)。假定MyViewGroup在DOWN消息派发过程中确定为目标。(这次流动的转折不是因为截断)
其实仔细想想,其设计还是很合理的,刚开始按下的时候,为什么要绕一大圈形成一个U形,是为了找到目标。找到目标后除了DOWN以外的消息都是精准投递,没有产生浪费。
上面的DEMO地址:https://github.com/ArronXiao/VerifyDemo 以后的验证也会在上面更新,持续维护!