转载请注意:http://blog.youkuaiyun.com/wjzj000/article/details/52493877
本菜GitHub上开源了一个小的Android项目,感兴趣的看官大大们可以star下:
https://github.com/zhiaixinyang/MyFirstApp
今天记录一下View的事件分发机制。(增加了全新的补充)
其实关于这方面有很多书籍博客都在讲,看别人的终究是别人的思路和理解。有必要自己重新记录一下,用自己的思考梳理一个属于自己的富强、民主、文明、和谐,自由、平等、公正、法治、爱国、敬业、诚信、友善的社会主义核心价值观。
首先既然谈到分发,那就说明控件至少是嵌套的。像这样
我来略微的解释一下这样图片。OneViewGroup和TwoViewGroup是继承了一个LinearLayout,并重写了:
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
//把方法名翻译过来:发送触摸事件
Log.d("AAAAAAA","OneViewGroup:dispatchTouchEvent");
return super.dispatchTouchEvent(ev);
}
//ViewGroup中特有方法,方法翻译过来就是拦截触摸事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.d("AAAAAAA","OneViewGroup:onInterceptTouchEvent");
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.d("AAAAAAA","OneViewGroup:onTouchEvent");
return super.onTouchEvent(event);
}
OneView是继承一个TextView。重写了:
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
Log.d("AAAAAAAAA","OneView:dispatchTouchEvent");
return super.dispatchTouchEvent(event);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.d("AAAAAAAAA","OneView:onTouchEvent");
return super.onTouchEvent(event);
}
当我点击OneView时,Log的信息是这样的:
那么接下来就让我们梳理一下这个过程:
首先是最下层的OneViewGroup中的dispatchTouchEvent()方法被调用。在OneViewGroup中紧接着调用onInterceptTouchEvent(),这个方法用于判断是否触发了
点击事件,也就是,是否调用自己的onTouchEvent()的方法。(很多地方称此为拦截事件,为啥我不这么说呢,因为我不喜欢这么说~)。如何判断是否调用,是通过
这个方法的返回值进行判断,如果这个方法返回true,那么OneViewGroup中的onTouchEvent()将会调用。返回false那么OneViewGroup中的事件处理到此结束,TwoViewGroup
将开始刚才OneViewGroup所进行的一系列过程....让我们把目光凝注在OneView中,过程还是如上述那样,但是我触摸了OneView,所以在OneView中的onInterceptTouchEvent()
中返回了true,onTouchEvent()被调用....OK,过程就是这样!

如果点击了OneViewGroup以及TwoViewGroup会怎么样呢?
![]()
点击TwoViewGroup后,TwoViewGroup中的onTouchEvet()被调用,这个事件被消费,所以OneView中的相关方法并没有被触发。
![]()
点击OneViewGroup后,效果同上....
但是如果我们仔细看,可以看到这几次的Log中好像有了问题,那就是在结束了onTouchEvent()后,
又重新走了一遍除了没有onInterceptTouchEvent()的方法的过程...我也不知道啊....16年10月19日,补充:
![]()
当父级控件的onInterceptTouchEvent()重写并返回true,那么父级控件重写的onTouchEvent()会执行。
如果父级控件返回的为false,那么将执行子控件重写了onTouchEvent()。如果子控件没有重写onTouchEvent()
那么父级控件中的onTouchEvent()将被执行。
这里有个值得注意的地方:
如果子控件即重写了onTouch,并且还重写了onClick。将会分情况执行:
如果onTouch中返回false,那么当触摸此控件时,依次执行onTouch以及onClick。
如果返回true,那么onClick将不会执行!其实也就是说,当onTouch中返回true说明事件到此彻底终止,
不在往下传递,也就是很多人说的事件被消费了。那么侧面我们也能得知,onClick是在onTouch之后被执行的。