相关文章
Android View体系(一)视图坐标系
Android View体系(二)实现View滑动的六种方法
Android View体系(三)属性动画
Android View体系(四)从源码解析Scroller
前言
三年前写过事件分发机制的文章但是写的不是很好,所以重新再写一篇,关于事件分发机制的文章已经有很多,但是希望我这篇是最简洁、最易懂的一篇。
1.处理点击事件的方法
View的层级
我们知道View的结构是树形的结构,View可以放在ViewGroup中,这个ViewGroup也可以放到另一个ViewGroup中,这样层层的嵌套就组成了View的层级。
什么是点击事件分发
当我们点击屏幕,就产生了触摸事件,这个事件被封装成了一个类:MotionEvent。而当这个MotionEvent产生后,那么系统就会将这个MotionEvent传递给View的层级,MotionEvent在View的层级传递的过程就是点击事件分发。
点击事件分发的重要方法
点击事件有三个重要的方法它们分别是:
- dispatchTouchEvent(MotionEvent ev):用来进行事件的分发
- onInterceptTouchEvent(MotionEvent ev):用来进行事件的拦截,在dispatchTouchEvent()中调用,需要注意的是View没有提供该方法
- onTouchEvent(MotionEvent ev):用来处理点击事件,在dispatchTouchEvent()方法中进行调用
为了了解这三个方法的关系,我们先来看看ViewGroup的dispatchTouchEvent()方法的部分源码:
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
...省略
if (actionMasked == MotionEvent.ACTION_DOWN
|| mFirstTouchTarget != null) {
final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
if (!disallowIntercept) {
intercepted = onInterceptTouchEvent(ev);
ev.setAction(action); // restore action in case it was changed
} else {
intercepted = false;
}
} else {
// There are no touch targets and this action is not an initial down
// so this view group continues to intercept touches.
intercepted = true;
}
...省略
return handled;
}
很明显在dispatchTouchEvent()方法中调用了onInterceptTouchEvent()方法来判断是否拦截事件,来看看onInterceptTouchEvent()方法:
public boolean onInterceptTouchEvent(MotionEvent ev) {
return false;
}
onInterceptTouchEvent()方法默认返回false,不进行拦截,接着来看看dispatchTouchEvent()方法剩余的部分源码:
public boolean dispatchTouchEvent(MotionEvent ev) {
...省略
final View[] children = mChildren;
for (int i = childrenCount - 1; i