Android_事件纷发
关于事件你应该知道的是
当一个事件产生后,他的传递过程遵循如下顺序Activity > Window > View
事件来源于activity,activity假如你没有重写任何关于事件纷发的方法的话,他会把事件传递给window,window将事件传递给decorView
现在我们来看下假如我们在activity中重写了dispatchEvent的方法是什么样的一个情况.
我们把activity中的dispatchTouchEvent 返回true
事件被activity的dispatchTouchEvent消耗掉,所以activity的
onTouchEvent方法得不到响应,我们看下log输出
很明显的能看出来,log只打印了dispatchTouchEvent中的相关方法,整个事件被dispatchTouchEvent消耗掉,并没有传递到我们的window > decorView 所有我界面的返回键接受不到事件,所以返回按钮的点击事件也没生效,
我们在把activity中的dispatchTouchEvent返回false看看是什么情况,,这也是我的一个疑问点,麻烦大神帮忙解答一下就是我activity中的dispatchTouchEvent返回了false,那么事件标志着事件没人处理,此时事件的根源是从activity来的,如果他都不管的话,这个事件已经不能返回他的父view ,当前activity的onTouchEvent()也无log输出,那么事件哪里去了????
然后我们看下返回false的log输出如下图:
log输出一只执行了activity中的dispatchTouchEvent的相关方法,
TouchEvent并没有任何输出,表明activity的onTouchEvent也没有接受到这个事件,此时我再点击返回键,的onclick依然是失效的,
所以.麻烦大神帮忙解答下这一点,当activity中的dispatchtouchevent返回false,事件的流程是怎么样的,???
最后我们让activity中的dispatchtouchevent 返回super看下
然后看下log日志的输出,以及log 的顺序,
注意log的顺序,dispatchTouchEvent down > onTouchEvent down
dispatchTouchEvent move > onTouchEvent move
dispatchTouchEvent up > onTouchEvent up
面试的时候注意面试官问的问题,和执行顺序的问题
然后我们往activity中加入一个linearlayout,我们重写一下linearlayout的有关事件的三个方法,并打印log看一下,暂时不往linearlayout中加入任何子view,单纯的看一下事件从activity传递到viewgroup的效果.
首先我们在书写一个TESTLinearlayout,如下
public class AAATestLinearlayout extends LinearLayout {
private static final String TAG = "AAATestLinearlayout";
public AAATestLinearlayout(Context context) {
super(context);
}
public AAATestLinearlayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public AAATestLinearlayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Logger.e(TAG, TAG + ">>>>dispatchTouchEvent.ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Logger.d(TAG, TAG + ">>>>dispatchTouchEvent.ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Logger.w(TAG, TAG + ">>>>dispatchTouchEvent.ACTION_UP");
break;
}
// return true;
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Logger.e(TAG, TAG + ">>>>onInterceptTouchEvent.ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Logger.d(TAG, TAG + ">>>>onInterceptTouchEvent.ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Logger.w(TAG, TAG + ">>>>onInterceptTouchEvent.ACTION_UP");
break;
}
// return true;
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Logger.e(TAG, TAG + ">>>>onTouchEvent.ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Logger.d(TAG, TAG + ">>>>onTouchEvent.ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Logger.w(TAG, TAG + ">>>>onTouchEvent.ACTION_UP");
break;
}
return super.onTouchEvent(event);
}
}
我们就先默认的让测试的linearlayout全部返回super值.
看下事件传递的过程从activity > window > decorView > 我们自己的linearlayout;
并且我们在linearlayout中的构造中设置了额外的onTouchLinstener,
我们看下的结果;
这里简答描述一下,我们往activity中加入了一个linearlayout.并且在构造中给linearlayoutset了一个touchlistener.
我们从log可以看到,事件从activity中开始传递,然后我们在linearlayout中有关事件的方法全部返回super.
其中关于onInterceptTouchEvent
我想说两句,这句话的返回值影响的是viewgroup容器中子view的事件传递,并不会对当前的viewgroup的onTouchEvent或者set 的touchlistener有影响,我们从log可以看出来,linearlayout的 onTouchEvent.down 和 touchliste的down均执行了
假如onInterceptTouchEvent的值返回的是super的话,我们看viewgroup的源码可以知道
默认是false,也就是不拦截…重要的是不拦截….
* appear here.
*
*
* @param ev The motion event being dispatched down the hierarchy.
* @return Return true to steal motion events from the children and have
* them dispatched to this ViewGroup through onTouchEvent().
* The current target will receive an ACTION_CANCEL event, and no further
* messages will be delivered here.
*/
public boolean onInterceptTouchEvent(MotionEvent ev) {
return false;
}
这是viewgroup的源码,和Android艺术探索第143页第六条说的完全吻合,
还有一篇博客,应该是比较经典的,其中对onInterceptTouchEvent的解释如下;
这里博客博主说是返回super的话默认被拦截,并把拦截的事件交给当前view,处理,
我们这里的当前view就是我们的linearlayoutlayout 从log看确实执行了onTouchEvent.但是这个onTouchEvent并不是因为返回了super他没有拦截而执行了.因为笔者试着返回true false,super,对我们设置的touchlistener和onTouchEvent的down事件没有任何影响,
所以这块我也迷茫了半天,看了书本和咨询了群里的nil大概猜测一下可能是博主理解有出入或者笔误,再次留下博客的地址:请大神批阅和校正一下原文链接如下Android编程下的事件纷发
接着说我们的场景,目前我们linearlayout中的事件处理方法均没有对事件做处理,这样我们linearlayout中的子view比如我们的返回按钮确实能接收到事件,然后点击返回箭头,activity关闭,此事第一个场景走完.
第二个场景,我们把我们的liearlayout中的dispatchTouchEvent返回true,我们猜想是这样的,如果返回true,事件就在当前的方法中终止了也就是在liearlayout中终止,所以其他的方法根本不会接收到这个事件,所以看下我们执行的log输出,
