您的位置:首页 > 移动开发 > Android开发

Android进阶之事件拦截处理机制

2016-08-19 10:50 453 查看

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控件架构与自定义控件讲解
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: