Android_事件纷发
2016-03-31 19:12
453 查看
关于事件你应该知道的是
当一个事件产生后,他的传递过程遵循如下顺序Activity > Window > View
事件来源于activity,activity假如你没有重写任何关于事件纷发的方法的话,他会把事件传递给window,window将事件传递给decorView
现在我们来看下假如我们在activity中重写了dispatchEvent的方法是什么样的一个情况.
我们把activity中的dispatchTouchEvent 返回true
![](http://img.blog.csdn.net/20160331141227747)
事件被activity的dispatchTouchEvent消耗掉,所以activity的
onTouchEvent方法得不到响应,我们看下log输出
![](http://img.blog.csdn.net/20160331141415919)
很明显的能看出来,log只打印了dispatchTouchEvent中的相关方法,整个事件被dispatchTouchEvent消耗掉,并没有传递到我们的window > decorView 所有我界面的返回键接受不到事件,所以返回按钮的点击事件也没生效,
我们在把activity中的dispatchTouchEvent返回false看看是什么情况,,这也是我的一个疑问点,麻烦大神帮忙解答一下就是我activity中的dispatchTouchEvent返回了false,那么事件标志着事件没人处理,此时事件的根源是从activity来的,如果他都不管的话,这个事件已经不能返回他的父view ,当前activity的onTouchEvent()也无log输出,那么事件哪里去了????
![](http://img.blog.csdn.net/20160331142027890)
然后我们看下返回false的log输出如下图:
![](http://img.blog.csdn.net/20160331142106641)
log输出一只执行了activity中的dispatchTouchEvent的相关方法,
TouchEvent并没有任何输出,表明activity的onTouchEvent也没有接受到这个事件,此时我再点击返回键,的onclick依然是失效的,
所以.麻烦大神帮忙解答下这一点,当activity中的dispatchtouchevent返回false,事件的流程是怎么样的,???
最后我们让activity中的dispatchtouchevent 返回super看下
![](http://img.blog.csdn.net/20160331142356704)
然后看下log日志的输出,以及log 的顺序,
![](http://img.blog.csdn.net/20160331142432767)
注意log的顺序,dispatchTouchEvent down > onTouchEvent down
dispatchTouchEvent move > onTouchEvent move
dispatchTouchEvent up > onTouchEvent up
面试的时候注意面试官问的问题,和执行顺序的问题
然后我们往activity中加入一个linearlayout,我们重写一下linearlayout的有关事件的三个方法,并打印log看一下,暂时不往linearlayout中加入任何子view,单纯的看一下事件从activity传递到viewgroup的效果.
首先我们在书写一个TESTLinearlayout,如下
我们就先默认的让测试的linearlayout全部返回super值.
看下事件传递的过程从activity > window > decorView > 我们自己的linearlayout;
![](http://img.blog.csdn.net/20160331160404541)
并且我们在linearlayout中的构造中设置了额外的onTouchLinstener,
我们看下的结果;
![](http://img.blog.csdn.net/20160331164501072)
![](http://img.blog.csdn.net/20160331164514948)
这里简答描述一下,我们往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,也就是不拦截…重要的是不拦截….
这是viewgroup的源码,和Android艺术探索第143页第六条说的完全吻合,
还有一篇博客,应该是比较经典的,其中对onInterceptTouchEvent的解释如下;
![](http://img.blog.csdn.net/20160331165643608)
这里博客博主说是返回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输出,
![](http://img.blog.csdn.net/20160331171632350)
![](http://img.blog.csdn.net/20160331171653069)
这里以为linearlayout中dispatchonTouchEvent返回了true,事件在这里终止了,所以我们的返回箭头就接收不到事件,于是我们的返回按钮就失效了.
第二个场景,我们让linearlayout的dispatchonTouchEvent返回false,那么这个触摸事件将是一个怎么样的过程呢?
dispatchonTouchEvent.返回false,事件要被来自哪里,就要被返回哪里,假如我们的linearlayout还有父view ,那么这个事件将返回给父view的onTouchEvent事件处理,如果来自activity,那么将被activity的onTouchEvent处理,看下我们的log输出;
![](http://img.blog.csdn.net/20160331173242497)
![](http://img.blog.csdn.net/20160331173415435)
当我们点击我们的返回箭头的时候,因为事件从liearlayout中返回给了activity消费,所以子控件没法接收到事件,所以点击返回的箭头也无法生效;
第三个场景,linearlayout中的onInterceptTouchEvent返回true,其他返回super,猜想,拦截事件返回true,那么事件不会传递给子view,
返回按钮不会生效.因为我们其他的方法都是返回到 super,所以事件在onTouchEvent中返回了给其父view 或者activity,由于activity中的onTouchEvent也返回到 super,所以事件消失,..具体看log输出的过程和解释
![](http://img.blog.csdn.net/20160331180843808)
![](http://img.blog.csdn.net/20160331180857448)
![](http://img.blog.csdn.net/20160331180910589)
因为事件也在activity中,并没有传递给子view 所以返回按钮失效
下一个场景,让我们的liearlayout中的onInterceptTouchEvent返回false,不拦截,那么事件将会传递给子view,子view在去调用自己的dispatch方法去纷发,这样事件就能被返回箭头接受,可以正常关闭activity
我们看下log输出,
![](http://img.blog.csdn.net/20160331182103219)
![](http://img.blog.csdn.net/20160331182119328)
由于onInterceptTouchevent返回了false,所以事件执行完他里面的方法后就把事件传递给了子view,于是事件就从发源地activity 和linearlayout中的 dispatch 和 intercept 起作用,并没有onTouchEvent的事情了,具体细节看log输出描述,然后由于事件传递给了子view 所以 返回箭头生效,这个方法返回false和返回super产生的效果是一模一样的,这里就不在截图了有兴趣的可以输出一下
到此为止我们activity中只有一个viewgroup的场景基本分析完毕了,然后我们想liearlayout中添加一个textview如下图
![](http://img.blog.csdn.net/20160331183123816)
因为我们这里加入的是最小单位的view就是view不能再添加额外的内容,我们手指触摸屏幕事件传递过程,有activity 到 liearlayout 在到view 在返回 linearlayout ,返回activity 直到消失,具体过程如下;
![](http://img.blog.csdn.net/20160331185247340)
![](http://img.blog.csdn.net/20160331185301403)
![](http://img.blog.csdn.net/20160331185320590)
再来一个场景,这次我们让childview中的dispatch 事件返回false,
笔者本来也是对这个传递有点模糊的,今天博客写到这里我都能猜到打印结果了,由于textviewdispatch返回了false ,所以事件执行完dispatch down后直接把事假返回给父view linearlayout的onTouchEvent,由于onTouchEvent设置了touchlistener 所以后执行,然后就是父view也返回了super,所以事件传递给activity的onTouchEvent 由于activity的onTouchEvent也返回了super.所以事件消失,最后在activity中执行 move 和 up
然后我们看下打印结果;
![](http://img.blog.csdn.net/20160331190811362)
![](http://img.blog.csdn.net/20160331190826768)
写到这里,理解的事件传递在脑海里的模糊场景已经有点透明了,还需要更多的实践,文中可能有理解不到位的也请大神批正,到此我理解的事件传递在viewgroup 和view中全部结束,也感谢群里nil的指点谢谢!
如果你看完还是对这个过程不是很理解,请自己模拟场景打印log,因为我感觉没有在比笔者更笨出身更贫寒的了,当你模拟看log有点想吐甚至能猜到不同的返回值会是什么样的传递场景,那么你对事件传递的过程相比之前你的理解肯定有恍然大悟的!谢谢….
当一个事件产生后,他的传递过程遵循如下顺序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. * </ol> * * @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输出,
这里以为linearlayout中dispatchonTouchEvent返回了true,事件在这里终止了,所以我们的返回箭头就接收不到事件,于是我们的返回按钮就失效了.
第二个场景,我们让linearlayout的dispatchonTouchEvent返回false,那么这个触摸事件将是一个怎么样的过程呢?
dispatchonTouchEvent.返回false,事件要被来自哪里,就要被返回哪里,假如我们的linearlayout还有父view ,那么这个事件将返回给父view的onTouchEvent事件处理,如果来自activity,那么将被activity的onTouchEvent处理,看下我们的log输出;
![这里写图片描述](http://img.blog.csdn.net/20160331173347685)
当我们点击我们的返回箭头的时候,因为事件从liearlayout中返回给了activity消费,所以子控件没法接收到事件,所以点击返回的箭头也无法生效;
第三个场景,linearlayout中的onInterceptTouchEvent返回true,其他返回super,猜想,拦截事件返回true,那么事件不会传递给子view,
返回按钮不会生效.因为我们其他的方法都是返回到 super,所以事件在onTouchEvent中返回了给其父view 或者activity,由于activity中的onTouchEvent也返回到 super,所以事件消失,..具体看log输出的过程和解释
因为事件也在activity中,并没有传递给子view 所以返回按钮失效
下一个场景,让我们的liearlayout中的onInterceptTouchEvent返回false,不拦截,那么事件将会传递给子view,子view在去调用自己的dispatch方法去纷发,这样事件就能被返回箭头接受,可以正常关闭activity
我们看下log输出,
由于onInterceptTouchevent返回了false,所以事件执行完他里面的方法后就把事件传递给了子view,于是事件就从发源地activity 和linearlayout中的 dispatch 和 intercept 起作用,并没有onTouchEvent的事情了,具体细节看log输出描述,然后由于事件传递给了子view 所以 返回箭头生效,这个方法返回false和返回super产生的效果是一模一样的,这里就不在截图了有兴趣的可以输出一下
到此为止我们activity中只有一个viewgroup的场景基本分析完毕了,然后我们想liearlayout中添加一个textview如下图
因为我们这里加入的是最小单位的view就是view不能再添加额外的内容,我们手指触摸屏幕事件传递过程,有activity 到 liearlayout 在到view 在返回 linearlayout ,返回activity 直到消失,具体过程如下;
再来一个场景,这次我们让childview中的dispatch 事件返回false,
笔者本来也是对这个传递有点模糊的,今天博客写到这里我都能猜到打印结果了,由于textviewdispatch返回了false ,所以事件执行完dispatch down后直接把事假返回给父view linearlayout的onTouchEvent,由于onTouchEvent设置了touchlistener 所以后执行,然后就是父view也返回了super,所以事件传递给activity的onTouchEvent 由于activity的onTouchEvent也返回了super.所以事件消失,最后在activity中执行 move 和 up
然后我们看下打印结果;
写到这里,理解的事件传递在脑海里的模糊场景已经有点透明了,还需要更多的实践,文中可能有理解不到位的也请大神批正,到此我理解的事件传递在viewgroup 和view中全部结束,也感谢群里nil的指点谢谢!
如果你看完还是对这个过程不是很理解,请自己模拟场景打印log,因为我感觉没有在比笔者更笨出身更贫寒的了,当你模拟看log有点想吐甚至能猜到不同的返回值会是什么样的传递场景,那么你对事件传递的过程相比之前你的理解肯定有恍然大悟的!谢谢….
相关文章推荐
- Android下使用Protobuf进行序列化
- 学到一个android小应用-霓虹灯闪烁效果界面
- Android 属性动画(Property Animation) 完全解析
- Android的性能优化
- Android 短信验证码平台
- android studio 开发常用快捷键使用分享
- Android 应用中使用ContentObserver自动填写短信验证码
- bank掉回弹效果
- Android中软键盘设置
- Android 初使用GreenDAO框架操作数据库
- Android设计模式(1)----单例模式
- 慕课-Android工程师-java入门第一季
- Android初学习 - 基础&进阶总结
- Android设计模式 单例模式(枚举单例)
- Android 5.0以上 获取当前正在运行的应用包名
- [置顶] Android Theme-安卓样式换肤实践方案
- Android初学习 - Activity的四种launchMode
- Android系统性能调优工具介绍
- challenge(六)图片异步加载类库(Android-Universal-Image-Loader)的使用
- 【Android性能优化】Android图片加载方案--Bitmap的内存管理和优化方案