android touch事件处理

来源:互联网 发布:linux c sleep 头文件 编辑:程序博客网 时间:2024/05/16 10:47

Touch事件消息流:

线程Looper收到Touch 消息

1、ViewRootImpl(Handler).dispatchMessage(Message)

 feature phone 的MMI_Task 一样

2、ViewRootImpl.handleMessage(Message) case PROCESS_INPUT_EVENTS

3、ViewRootImpl.processInputEvents(boolean)

过滤无效事件

4、ViewRootImpl.handleMessage(Message) case DISPATCH_POINTER

5、ViewRootImpl.deliverPointerEvent(MotionEvent, boolean)

6、发送PointerEvent到View Tree (View Hierarchy)

View Tree 的Root收到该消息调用View dispatchPointerEvent(MotionEvent)不能重写。

dispatchPointerEvent比较简单,贴出代码

if (event.isTouchEvent()) {

returndispatchTouchEvent(event);

}else {

    returndispatchGenericMotionEvent(event);

}

7、View Tree 的Root 调用dispatchTouchEvent(event)

如果目标为ViewGroup,比较重要的有几个过程:

1、4.0 为保持Touch事件的一致性,每次Down事件的时候,会清空前一次的状态。即保持Down->Move->Up的消息顺序,不可能出现Down->Move->Down。注:2.3是直接丢弃Down事件。

2、对于onInterceptTouchEvent的调用,这是上层应用重写onInterceptTouchEvent,来截获事件的实现。Return true 截获事件,往自己的OnTouchEvent发送该事件,return false不截获,具体参见android文档。当然并不是每个都能截获的,如果FLAG_DISALLOW_INTERCEPT被置位的话,是不能被截获的。一般发生这种情况的主要是系统有比较重要的事件通知整棵View树。

       3、层层遍历,将Touch事件发送到叶子节点,然后根据返回值决定是否,让其他节点处理Touch事件,return true 该事件处理到此结束,return false继续处理

如果目标为View。那它只能为叶子节点,因为它不能包含任何View。一些关键的处理如下

if (li != null &&li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) ==ENABLED && li.mOnTouchListener.onTouch(this, event)) {

  return true;

}

if (onTouchEvent(event)) {

  return true;

}

这段话主要的意思就是如果这个View设置了OnTouchListener那么调用接口OnTouch,然后consume掉这个事件,即不再继续处理。如果没有的话,调用自己的OnTouchEvent。

举个例子,一个白板的View,没有设置TouchListener也没有重写OnTouchEvent,那么这个View就直接调用View的OnTouchEvent,View的OnTouchEvent实现如下:

代码太长,翻成文字可以这么理解:

       如果该View 是disable 状态:那么给它加上pressed标志位,重绘一下(在屏幕上显示为灰显按下去的效果)

       如果该View不是disable状态,并且是clickable,那么在ACTION_DOWN的时候会加上pressed标志位,并启动一个timer(长按事件)。重绘一下(显示出按下去的效果)。

此时还是MOVE事件监视该View的状态,如果这个MOVE滑出了该View的范围,那么会复位View的click状态。UP事件时,会检查是否已经执行过LongPress,如果已经执行了LongPress,那么就不执行了Click,反之,会取消掉LongPress的Timer,然后在执行Click。

在UP事件的最后,做一下收尾处理,完事。

所以TouchEvent是Click 和 LongPress的底层实现,View的派生类如Button等等就不需要重写OnTouchEvent。