1 Android控件架构
文章图片
文章图片
文章图片
1 简单的总结 (1)父View优先拦截当前事件,拦截不成功就让子View对当前事件进行拦截。
(2)如果拦截成功的话,就会沿着子view到父View的路径查找onTouchEvent返回true的那个子View,让该子View对该事件进行处理;
(3)同时如果某一个View对当前事件拦截成功的话,当前事件就不会继续分发给这个View的子View。
2 事件分发与处理
2.1 结论
(1)android对事件分发的顺序为:Activity–>PhoneWindow->DecorView->yourView;
(2)android控件对事件处理的优先级:onTouch>onTouchEvent>onClick
2.2 事件分发
android既然可以对事件进行拦截,肯定有某个方法对事件进行的传递或者分发。完成事件分发功能的方法由Activity的dispatchTouchEvent(MotionEvent ev)l来负责:
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
//该方法为空方法,直接忽略之
onUserInteraction();
}
//把事件ev交给phoneWindow来处理
if (getWindow().superDispatchTouchEvent(ev)) {
//表明整个事件到此结束,处理完毕
return true;
}
//说明该事件在View中没有得到处理,由Activity自己处理
//至于怎么处理博客后面后有说明
return onTouchEvent(ev);
}
PhoneWindow方法都做了些什么:
@Override
public boolean superDispatchTouchEvent(MotionEvent event) {
return mDecor.superDispatchTouchEvent(event);
}
就是把此次事件直接很光棍的传给DecorView,这个View是所有视图的根视图,Activity界面中你能见到的各个View都是DecorView的子View。
2.3 事件处理
到此为止事件已经分发到View上面,View获取到事件后有两个选择:处理和不处理该事件,如果处理该事件那事件就不会继续向其子View分发下去;否则就继续分发下去交给子View对该事件做同样的判断,其实就是个递归的过程。
先用如下的伪代码也表示一下事件处理流程:
public boolean dispatchTouchEvent(event){
//如果当前View对此事件拦截成功
if(this.onInterceptTouchEvent(event)){
//由当前View对此事件进行处理
//true 表示处理了该事件,false表示没有处理该事件
return onTouchEvent(event);
}else{//没有拦截成功
//交给子类来分发拦截处理
return child.dispatchTouchEvent(event);
}
}
更直观的用流程图可以如下表示:
文章图片
其实通过上面的代码也可以得出这个结论:当Activity中所有的视图View都不处理该事件的是就交给Activity的onTouchEvent方方来处理。
2.4 分析ViewGroup分发事件
(1)ViewGroup永远不会对拦截,因为他的onInterceptTouchEvent(MotionEvent ev)始终返回的是false!这样DecorView对到来的事件MotionEvent就只有分发到子View并由子View进行拦截和处理此事件了.
(2)View包括直接继承于View的子类因为其父类View没有onInterceptTouchEvent方法,所以没法对事件进行拦截,如果这种View获取到了事件,那么就会执行onTouchEvent方法。
3 图例解析 3.1 情况1
如果A的InterceptTouchEvent返回了true,其余的仍然返回false,那么执行输出的log为:
文章图片
转换成效果图为:
文章图片
可以发现此时A拦截了此次Touch事件,事件不再向A的子控件B、C、D传递。此时所有的action事件比如手指移动ACTION_MOVE或者ACTION_UP等事件都交给A的onTouchEvent方法去处理(当然这是在onTouchEvent方法返回true的情况下,如果返回false经过测试时不会相应这些action的)。B、C、D控件是的事件处理拦截方法和事件处理方法是无法得到执行的。
3.2 情况2
只有B的onIntercepteTouchEvent事件返回了true的情况下,打印的log为
文章图片
转换成效果图为:
文章图片
3.3 情况3
同理可知,C控件的onIntercept方法返回了true的情况下,其余的仍然返回false的情况下,输出log为
文章图片
转换成效果图为
文章图片
3.4 下面说说各个view的onTouchEvent返回true的情况
由于onTouchEvent事件是从子控件到父控件传递的,当D的onTouchEvent返回true的时候,经测试输出效果如下
文章图片
转换成效果图为:
文章图片
经过测试发现,此时D处理了此次Touch事件的各种action,C B D是的onTouchEvent的没有得到执行。
同理当C的onTouchEvent方法返回了true的时候,输出的log如下
文章图片
转换成效果图如下:
文章图片
4 参考链接 android事件拦截处理机制详解
从源码角度分析android事件分发处理机制
【Android进阶之事件拦截处理机制】 Android群英传笔记——第三章:Android控件架构与自定义控件讲解
推荐阅读
- Android进阶|Android官方文档之Services
- android|【Android进阶】如何写一个很屌的动画(1)---先实现一个简易的自定义动画框架
- Android:仿“某音”APP 多头像跳动动画+轮播动画+心跳动画+输入框抖动动画
- Android RxJava第一弹之原理详解、使用详解、常用场景(基于Rxjava2.0)
- Android应用层|Android事件总线(一)EventBus3.0用法全解析
- EventBus3.0的使用详解
- Android进阶|手撸一个简单的网络框架
- Android框架层|腾讯面试官(了解Java Binder中的系统服务吗())
- Android进阶|Android Binder原理(四)ServiceManager的启动过程