一个现在有点想法的IT民工
分类: Android平台
2014-03-24 13:56:40
Android底层模块获得触摸消息后,通过pipe将消息传到上层,然后WMS(window manager service)把消息分发给具体的客户端,ViewRoot的mInputHandler对象经过一定处理通过mView.dispatchTouchEvent()派发给根视图。
根视图会根据触摸位置来递归计算找到子视图并同时把事件传递给子视图。在此过程的大概流程是:
1. 先调用父视图的dispatchTouchEvent(),dispatchTouchEvent()中视情况会回调onInterceptTouchEvent();
2. 如果onInterceptTouchEvent()没有消耗该消息(返回false),则会递归调用子View的dispatchTouchEvent();若onInterceptTouchEvent()消耗了此消息(返回true),则会调用父view本身的onTouchEvent(),此情况下父视图的 onTouchEvent()默认返回false。
3. 到子View的dispatchTouchEvent()后:如果子视图为viewGroup,则重复1、2步骤;如果子视图为单独的view,则调用view本身的onTouchEvent(),如果view的onTouchEvent()(默认一般消耗掉消息,返回true)没有消耗该消息,则返回到父视图,调用父视图的onTouchEvent()(默认返回false),依此递归返回。
备注:在上面的递归过程中,可以这样看(视图结构:C包含B,B包含A):当找到某个视图A处理了该消息后(第一个消息应该是DOWN), B中相当于找到了处理接收该事件的target(target变量指向A),C中也是。那么从A中返回后,B、C中都不再理此消息了。后续过来的MOVE, UP消息由C->B->A的过程中也会经过C、B的onInterceptTouchEvent(),就是说C、B还可以拦截。如果A没处理(返回false),那么C、B中都没有target了,那么后续过来的MOVE、UP消息直接被忽略,不会回调到任何onInterceptTouchEvent()和onTouchEvent()中。
如果A没处理(返回false),B处理了(可能:C. onInterceptTouchEvent()->B. onInterceptTouchEvent()(返回true) ->B. onTouchEvent()(返回true)或者:C. onInterceptTouchEvent()->B. onInterceptTouchEvent()(返回false) ->A. onTouchEvent()(返回false)-> B. onTouchEvent()(返回true))。那么C的target指向B,后续的MOVE、UP消息由C->B,会经过C的onInterceptTouchEvent(),但不会经过B的onInterceptTouchEvent()(因为target已经是B了),直接派发给B的onTouchEvent()。
从备注所述过程应该能找出点touch事件传递的规律了。
注意在最外层根视图的dispatchTouchEvent()中,会先判断是否存在callback对象。对应用窗口而言,此callback对象就是activity。如果有callback,则会调用callback的dispatchTouchEvent(),activity的dispatch会先调onUserInterception(),如果没有消耗该消息,则把消息又重新给根视图,进行如上处理。