基础认知
1. 事件
- 定义
当用户触摸屏幕时(View 或 ViewGroup派生的控件),将产生点击事件(Touch事件)。
Touch事件的相关细节(发生触摸的位置、时间等)被封装成MotionEvent
对象。 - 事件类型(4种)
事件类型 | 具体动作 |
---|---|
MotionEvent.ACTION_DOWN | 按下View(所有事件的开始) |
MotionEvent.ACTION_UP | 抬起View(与DOWN对应) |
MotionEvent.ACTION_MOVE | 滑动View |
MotionEvent.ACTION_CANCEL | 结束事件(非人为原因) |
- 事件列
一般情况下,事件列都是以DOWN
事件开始、UP
事件结束,中间有无数的MOVE事件,如下图:
2. 事件分发的本质
将点击事件(MotionEvent
)传递到某个具体的View & 处理的整个过程。
3. 事件在哪些对象之间进行传递?
Activity、ViewGroup、View。
4. 事件分发的顺序
事件传递的顺序:Activity -> ViewGroup -> View。
5. 事件分发过程由哪些方法协作完成?
dispatchTouchEvent() 、onInterceptTouchEvent()和onTouchEvent()。
事件分发机制 源码分析
Android事件分发流程: Activity -> ViewGroup -> View。
1. Activity的事件分发机制
当一个点击事件发生时,事件最先传到Activity #dispatchTouchEvent()
进行事件分发。
// Activity#dispatchTouchEvent
public boolean dispatchTouchEvent(MotionEvent ev) {
// 一般都是true, 时间列都是从DOWN开始
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
// 作用:实现屏保功能
// a. 该方法为空方法
// b. 当此activity在栈顶时,触屏点击按home,back,menu键等都会触发此方法
onUserInteraction();
}
// PhoneWindow的superDispatchTouchEvent实现:mDecor.superDispatchTouchEvent(event)
// 事件传递:Activity => ViewGroup
if (getWindow().superDispatchTouchEvent(ev)) {
return true;
}
// Activity#onTouchEvent的实现:mWindow.shouldCloseOnTouch(this, event)
return onTouchEvent(ev);
}
2. ViewGroup的事件分发机制
3. View的事件分发机制
总结
/**
* 点击事件产生后, ViewGroup
*/
// 步骤1:调用dispatchTouchEvent()
public boolean dispatchTouchEvent(MotionEvent ev) {
boolean consume = false; //代表 是否会消费事件
// 步骤2:判断是否拦截事件
if (onInterceptTouchEvent(ev)) {
// a. 若拦截,则将该事件交给当前View进行处理
// 即调用onTouchEvent ()方法去处理点击事件
consume = onTouchEvent (ev) ;
} else {
// b. 若不拦截,则将该事件传递到下层
// 即 下层元素的dispatchTouchEvent()就会被调用,重复上述过程
// 直到点击事件被最终处理为止
consume = child.dispatchTouchEvent (ev) ;
}
// 步骤3:最终返回通知 该事件是否被消费(接收 & 处理)
return consume;
}
总结:
- dispatchTouchEvent()、 onTouchEvent() 消费事件、终结事件传递(返回true);
- 而onInterceptTouchEvent 并不能消费事件,它相当于是一个分叉口起到分流导流的作用,对后续的ACTION_MOVE和ACTION_UP事件接收起到非常大的作用。