事件MotionEvent包含了哪几个?
ACTION_DOWN
手指触碰到屏幕时触发,只会执行一次ACTION_MOVE
手指在屏幕上滑动出发,会执行多次ACTION_UP
手指抬起离开屏幕出发,只会执行一次ACTION_CANCEL
事件被上层拦截时会触发- 父容器
ViewGroup
需要从子View
手中抢夺分发的事件进行处理时,会用到ACTION_CANCEL
ViewGroup
的事件分发中,通过如下代码会将事件状态置为ACTION_CANCEL
:
final boolean cancelChild = resetCancelNextUpFlag(target.child) || intercepted;
- 所以,在父容器
ViewGroup
在进行事件分发时,父容器ViewGroup
需要将事件从子View
中抢夺过来;- 处理第一次
ACTION_MOVE
事件中,cancelChild
值为true
时,会通过dispatchTransformedTouchEvent()
方法中,将状态更改为ACTION_CANCEL
,这个操作会执行一次子View
的事件分发dispatchTouchEvent
方法,并且状态是ACTION_CANCEL
,也就是说子,这会将子View
没有消费该事件View
中的事件剥夺给到父容器ViewGroup
; - 在父容器中进行第二次
ACTION_MOVE
的操作时,父容器ViewGroup
进行事件处理
- 处理第一次
- 父容器
总结:
View
是负责事件处理onTouchEvent
的,而ViewGroup
主要是负责事件分发的dispatchTouchEvent()
.
事件的接收流程?(事件是在哪里接收的?)
- 通过
WindowInputEventReceiver
接收事件
- 在
ViewRootImpl.java
的setView()
方法中,通过如下对象WindowInputEventReceiver
去接收我们的事件,代码如下:
mInputEventReceiver = new WindowInputEventReceiver(inputChannel, Looper.myLooper());
- 接收到的事件最后进入到
Activity
的dispatchTouchEvent()
去处理,过程如下:
- 接着我们去研究
WindowInputEventReceiver
中的onInputEvent
方法, - 然后调用
enqueueInputEvent
方法, - 接着调用
doProcessInputEvents
方法, - 然后调用
deliverInputEvent(q)方法
, - 接着调用
stage.deliver(q)
方法, - 接着调用
onProcess(q)
方法,注意这里stage
实际调用的是实现类ViewPostImeInputStage
的onProcess
方法, - 接着调用
processPointerEvent(q)
方法, - 然后调用
mView.dispatchPointerEvent(event)
,注意这里的mView
是DecorView
,在DecorView
的终极超类View
中才有重写dispatchPointerEvent(event)
方法; - 接着调用
View.java
中的dispatchTouchEvent
方法,这里会调用到实现类DecorView
中的dispatchTouchEvent
方法, - 这里会通过
cb.dispatchTouchEvent(ev)
调用到Activity
中的dispatchTouchEvent()
方法- 解释说明
Activity
由来://这里的变量cb其实是Activity, //因为在(PhoneWindow)Window中setCallback(callback)方法, //传入的参数值是Activity的this引用 Window.Callback cb = mWindow.getCallback();
- 解释说明
- 接着从
Activity
中的dispatchTouchEvent()
方法往下分析; - 接着执行
PhoneWindow
中的superDispatchTouchEvent()
方法; - 接着执行
DecorView
中的