在介绍点击事件的传递规则之前,首先我们要明白我们要分析的对象是什么,MotionEvent即点击事件。所谓点击事件的事件分发,其实就是MotionEvent事件的分发过程,当我们点击手机屏幕的时候,就产生了一个点击事件,即MotionEvent,Android系统需要把这个事件传递给一个具体的View,这个传递的过程就是分发过程。有人会说了,这不就是简单的一个点击吗,这有什么好分析的。如果你抱有这样的想法,说明你没有碰到过点击冲突的问题,如果出现了这样的问题,你不理解分发机制的话,那就焦头烂额了。废话少说,直接进正题。
三个很重要的方法
public boolean dispatchTouchEvent(MotionEvent event)
用于进行事件的分发,如果事件能够传递给当前的view,那么此方法一定会被调用,返回结果受当前view的onTouchEvent和下级view的dispatchTouchEvent方法的影响,表示是否消耗当前的事件
public boolean onInterceptTouchEvent(MotionEvent event))
在dispatchTouchEvent方法内部调用,用来判断是否拦截某个事件,如果当前view拦截了某个事件,那么在同一个事件序列当中,此方法不会被再次调用,返回结果表示是否拦截当前事件。
public boolean onTouchEvent(MotionEvent event)
在dispatchTouchEvent方法中调用,用来处理点击事件,返回结果表示是否消耗当前事件,如果不消耗,则在同一个事件序列中,当前view无法再次接收事件。
那么上面的三个方法有什么区别呢?他们是什么关系呢?下面用一段伪代码表示:
public boolean diapatchTouchEvent(MotionEvent ev) {
boolean consume = false;
if(onInterceptTouchEvent(ev)) {
consume = onTouchEvent(ev);
} else {
consume = child.dispatchTouchEvent(ev);
}
return consume;
}
上面的伪代码已经说的很清楚了。
对于一个根ViewGroup来说,点击事件产生后,首先会传递给它,这时它的dispatchTouchEvent就会被调用,如果这个ViewGroup的onInterceptTouchEvent方法返回true就表示它要拦截当前事件,接着事件就会交给这个ViewGroup处理,即它的onTouchEvent方法就会被调用。如果返回false就表示它不拦截当前事件,这是事件就会继续传递给它的子元素,接着子元素的diapatchTouchEvent方法就会被调用,直到时间爱你被最终处理。
转载自任玉刚大神的 Android 开发艺术探索