View事件分发机制
本章节将详细介绍Android中View的事件分发机制,包括事件传递流程、源码分析和常见面试题。
核心问题
- 简述Android的事件分发机制
- Activity、ViewGroup、View三者的事件分发顺序是怎样的?
- 如何解决滑动冲突?
事件分发流程
基本流程
事件分发的顺序是:Activity -> Window -> DecorView -> ViewGroup -> View
// ViewGroup的事件分发方法
public boolean dispatchTouchEvent(MotionEvent ev) {
boolean handled = false;
if (onInterceptTouchEvent(ev)) {
handled = onTouchEvent(ev);
} else {
handled = child.dispatchTouchEvent(ev);
}
return handled;
}关键方法
- dispatchTouchEvent:事件分发
- onInterceptTouchEvent:事件拦截
- onTouchEvent:事件处理
源码分析
Activity的分发起点
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
onUserInteraction();
}
if (getWindow().superDispatchTouchEvent(ev)) {
return true;
}
return onTouchEvent(ev);
}实践应用
滑动冲突解决方案
- 外部拦截法
- 内部拦截法
示例代码
// 外部拦截法
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean intercepted = false;
int x = (int) ev.getX();
int y = (int) ev.getY();
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
intercepted = false;
break;
case MotionEvent.ACTION_MOVE:
if (父容器需要当前点击事件) {
intercepted = true;
} else {
intercepted = false;
}
break;
case MotionEvent.ACTION_UP:
intercepted = false;
break;
}
return intercepted;
}面试题解析
Q1:事件传递的返回值的含义?
- true:事件被消费,不再继续传递
- false:事件未被消费,继续传递给父View的onTouchEvent
Q2:View的onTouchEvent默认返回值?
- 可点击(clickable为true):返回true
- 不可点击:返回false
Q3:事件分发的核心原理?
基于责任链模式,从顶层ViewGroup开始,逐层分发事件,直到找到合适的处理者。