Android 事件分发细说
2016-06-06 11:54
519 查看
一直以来都对Android 的事件分发机制有疑惑,以前只知道事件分发涉及到三个方法:
首先也是这3个方法:
可能看了上面3个方法有点懵逼。这里一个一个的解释。
上面的代码简单粗暴有木有?上面的代码把机制展现得淋漓尽致了。
首先调用
假设我们有以下场景。有一个
事件的传递顺序是这样的:
这样很好理解,假设我在ParentView和ChildView的3个方法都没有做处理的话,事件的传递过程就是:
还不够清楚?如下图:
只要明白了以上的原理,就能根据不同的业务需求进行拦截等相关操作了。
最后有一些小知识点需要注意的:
如果
如果
有一种场景,如果一个
结论
一个事件的序列是从手指按下到手指抬起的整个过程,中间会有
一个事件如果某个
如果
如果一个
dispatchTouchEvent、
onInterceptTouchEvent、
onTouchEvent。三个方法分别为分发事件,拦截事件,处理事件,对于这些知识一知半解,并没有深入了解。当遇到滑动冲突的时候就在父View或者子View的这三个方法,
return true or false,一个个试(笨~)。上网看别人的博客,篇幅太长并且看得我一愣一愣的,我有点方。今天终于理解的比较完整了,我尝试以一种直观简单的方法描述这里面的流程。
首先也是这3个方法:
dispatchTouchEvent,事件的分发,事件传到当前
View的话一定会调用,内部调用了
onInterceptTouchEvent和
onTouchEvent,返回结果表示是否消耗当前事件,不消耗就向上层传递。
onInterceptTouchEvent,用来判断是否拦截某个事件。
onTouchEvent,用来判断是否消耗事件。
可能看了上面3个方法有点懵逼。这里一个一个的解释。
dispatchTouchEvent的内部实现伪代码简化之后是这样的。
@Override public boolean dispatchTouchEvent(MotionEvent e){ boolean consume = false; if(onInterceptTouchEvent(e)){ comsume = onTouchEvent(e); }else{ consume = child.dispatchTouchEvent(e); } return consume; }
上面的代码简单粗暴有木有?上面的代码把机制展现得淋漓尽致了。
首先调用
onInterceptTouchEvent询问是否拦截,如果拦截,就由
onTouchEvent处理,否则
else就由
childView的
dispatchTouchEvent决定。
假设我们有以下场景。有一个
Activity,然后里面嵌套了2个
View,一个是
ParentView,一个是
ChildView。那么事件的传递是怎么样的呢。
事件的传递顺序是这样的:
Activity -> Window -> View,假设我的
ParentView得到事件之后,
ParentView#dispatchTouchEvent来进行判断。然后调用了
ParentView#onInterceptTouchEvent,如果
ParentView#onInterceptTouchEvent返回
true,就会调用
ParentView#onTouchEvent。如果返回了
false就会调用
ChildView#dispatchTouchEvent,然后重复上面的过程。
这样很好理解,假设我在ParentView和ChildView的3个方法都没有做处理的话,事件的传递过程就是:
ParentView -> dispatchTouchEvent
ParentView -> onInterceptTouchEvent ->return false
ChildView -> dispatchTouchEvent
ChildView -> onInterceptTouchEvent
ChildView ->onTouchEvent
ParentView ->onTouchEvent
Activity -> onTouchEvent
还不够清楚?如下图:
只要明白了以上的原理,就能根据不同的业务需求进行拦截等相关操作了。
最后有一些小知识点需要注意的:
如果
View设置了
onTouchListener,会先执行
OnTouchListener的
onTouch方法。如果该方法返回
true,表示消费了。不会执行
onTouchEvent了,如果
onTouch返回
false,就会继续执行
onTouchEvent
如果
View设置了
OnClickListener的话,会在
onTouchEvent中调用
listener.onClick(this);
有一种场景,如果一个
ViewGroup和它的
childView都在
onTouchEvent返回了
false,根据上面的
dispathchTouchEvent分发机制,事件会传到
ViewGroup的
onTouchEvent,如果
ViewGroup的
onTouchEvent也返回了
false的话,就会返回到
Activity,
Activity的
onTouchEvent就会被调用。
结论
一个事件的序列是从手指按下到手指抬起的整个过程,中间会有
ACTION_DOWN,
ACTION_MOVE,
ACTION_UP的过程
一个事件如果某个
View拦截了,那么这个
View会处理整个事件序列。
如果
View决定拦截某个事件的话,就会交给
onTouchEvent处理,在一个事件序列中不会再调用
onInterceptTouchEvent。
如果一个
View的决定拦截某个事件
(onInterceptTouchEvent return true),则在处理
ACTION_DOWN的时候,如果返回
false,表示他不处理这个事件,这时候
dispatchTouchEvent就会返回
false,那么后续事件就会交给上层
View处理,就不会再调用这个
View的
onTouchEvent了。也就是说后续的
ACTION_MOVE、
ACTION_UP都不会调用它的
TouchEvent了,都交由父级
View来处理。
View的
onTouchEvent默认返回
true。
View的
longClickable和
clickable都为
false的时候就会返回
true。
childView可以通过
requestDisallowInterceptTouchEvent()方法请求阻止或运行父
View的事件分发过程。
相关文章推荐
- android studio 更改背景和设置字体大小
- Android 崩溃日志 本地存储 与 远程保存
- Android自定义PopupWindow显示在控件上方或者下方
- Android UI设计系列之自定义Dialog实现各种风格的对话框效果(7)
- 【Android基础知识】ContentProvider(二)自定义ContentProvider和URI
- 嘿!让我们来手动编译安卓项目吧
- Android性能优化总结
- android xampp study ---1
- Android UI设计系列之HTML标签实现TextView设置中文字体加粗效果(6)
- Google Android开发者文档系列-创建有内容分享特性的应用之接收其它应用程序发送的简单数据
- Android开发笔记(一百零四)消息推送SDK
- Parcel学习
- Android资源文件命名规则
- 修改android签名证书keystore
- ClassCastException:ColorDrawable cannot be cast to RoundRectDrawableWithShadow
- Android UI设计系列之自定义DrawView组件实现数字签名效果(5)
- Android乐学成语的实现分析
- 六款值得推荐的android(安卓)开源框架简介
- [转]框架模式 MVC 在Android中的使用
- Android handler使用总结