当点击的时候,会先调用顶级viewgroup的dispatchTouchEvent,如果顶级的viewgroup拦截了此事件(onInterceptTouchEvent返回true),则此事件序列由顶级viewgroup处理。如果顶级viewgroup设置setOnTouchListener,则会回调接口中的onTouch,此时顶级的viewgroup中的onTouchEvent不再回调,如果不设置setOnTouchListener则onTouchEvent会回调。如果顶级viewgroup设置setOnClickListener,则会回调接口中的onClick。如果顶级viewgroup不拦截事件,事件就会向下传递给他的子view,然后子view就会调用它的dispatchTouchEvent方法。
1.触发过程:Activity->Window->DocerView->ViewGroup->View,View不触发再返回由父级处理依次向上推。 2.在每个阶段都要经过三个方法 dispatchTouchEvent(分发)、onInterceptTouchEvent(拦截)、onTouch(处理)
大体流程: Activity中走了Window 的 dispatch,Window 的 dispatch 方法直接走了 DocerView 的 dispatch 方法,DocerView 又直接分发给了 ViewGroup,ViewGroup 中走的是 onInterce 判断是否拦截,拦截的话会走 onTouch 来处理,不拦截则继续下发给 View。到 View 这里已经是最底层了,View 若继续不处理,那就调用上层的 onTouch 处理,上层不处理继续往上推。
推荐一篇介绍非常详细的博客:https://www.jianshu.com/p/38015afcdb58
给大家举个形象的例子吧。ViewGroup相当于老板或者部门管理。View相当于员工。onTouchEvent相当于接业务。dispatechTouchEvent相当于处理任务。onIterceptTouchEvent相当于拦截任务。 先来分配角色
现在模拟来业务了(点击事件) 老板(ViewGroup)接到业务(onTouchEvent),他有两个选择
然后X部门领导接到任务,部门管理者有两个选择
领导接到员工的反馈,告诉老板(return true|renturn false)。
责任链模式
事件来源:input -> window -> ViewRoot -> DecorView -> Activity -> ... 事件处理:责任链模式,先从顶层传到底层,再从底层传回顶层,如果中间被消费或拦截,则流程结束 从Activity.dispatchTouchEvent()开始 --向下--> ViewGroup.dispatchTouchEvent(),可通过onInterceptTouchEvent()拦截 --向下--> View.dispatchTouchEvent() --向下--> View.onTouchEvent() --向上--> ViewGroup.onTouchEvent() --向上--> Activity.onTouchEvent() 注意点:如果View没有消费ACTION_DOWN,后面的其他事件就不会再传过来
1.触发过程:Activity->Window->DocerView->ViewGroup->View,View不触发再返回由父级处理依次向上推。 2.在每个阶段都要经过三个方法 dispatchTouchEvent(分发)、onInterceptTouchEvent(拦截)、onTouch(处理) 大体流程: Activity中走了Window 的 dispatch,Window 的 dispatch 方法直接走了 DocerView 的 dispatch 方法,DocerView 又直接分发给了 ViewGroup,ViewGroup 中走的是 onInterce 判断是否拦截,拦截的话会走 onTouch 来处理,不拦截则继续下发给 View。到 View 这里已经是最底层了,View 若继续不处理,那就调用上层的 onTouch 处理,上层不处理继续往上推。 推荐一篇介绍非常详细的博客:https://www.jianshu.com/p/38015afcdb58
View是没有onInterceptTouchEvent(拦截)的方法的
之前写过一篇文章回顾时间分发机制,希望能有补充。 深入理解Android事件分发机制
1.当我们按下手指,ViewGroup的onInterceptTouchEvent会最先处理down事件。 假设1:onInterceptTouchEvent返回false,子view的onTouchEvent返回true,后续的move和up事件都将传到onInterceptTouchEvent中,然后一层一层的传递下去交给子view处理 假设2:onInterceptTouchEvent返回false,子view的onTouchEvent返回的是false,则后续的move和up事件都将交给ViewGroup的onTouchEvent处理,如果ViewGroup的onTouchEvent返回为true,ViewGroup将会自己处理,如果ViewGroup的onTouchEvent返回false,则会继续向上传递,交给ViewGroup的父亲来处理。 假设3:onInterceptTouchEvent返回true,那么down和后续的move和up事件将会交给ViewGroup的onTouchEvent处理
当顶级的ViewGroup接收到事件消息之后,会调用dispatchTouchEvent 方法进行分发事件, 在分发时会先去判断该事件是否拦截onInterceptTouchEvent。如拦截,则事件不继续进行 分发,自己进行消费。如不拦截,事件继续进行向下传递到子控件,如果子控件是ViewGroup 则继续走上述操作,如果是View则会走onTouchEvent方法。 其中ViewGroup不拦截之后会先走onTouch方法,该方法会影响其onTouchEvent。整体传递是一个责任链模式
事件分发的细节真的非常多,用老板员工的例子,最早开始看的时候我是没记住过。如果你只是看别人得出来的结论,那么十个人他能总结出十种自己的结论,看似好像明白了,过一段时间自己去看还是会忘记,所以我觉得想要真的明白就得自己去跟踪源码,然后用关键代码提炼成伪代码,打log看结果,做好笔记。由于你没法获得自己手机的系统源码,所以最好用模拟器来调试,用模拟器对应的sdk版本编译运行代码,自定义几个简单的View和ViewGroup,从ViewGroup的dispatchTouchEvent()方法处开始打断点。这里分享一个小技巧,如果你想要程序在执行到你自定义ViewGroup的dispatchTouchEvent()处暂停,可以在断点的condition处加上this.getClass().getSimpleName().equals("CustomViewGroup1");这样的条件语句。后续总结完毕,我会发文章出来给大家参考的,大家有问题可以互相交流,共同进步。
事件分发机制是责任链模式,先从顶层传到底层,再从底层传回顶层,如果中间被消费或拦截,则流程结束: Activity dispatchTouchEvent- >ViewGroup dispatchTouchEvent ->ViewGroup onInterceptTouchEventview->View dispatchTouchEvent -> ->View onTouchEvent-> ViewGroup onTouchEvent->Activity onTouchEvent 事件监听分别有 dispatchTouchEvent(分发)onInterceptTouchEvent(拦截)onTouchEvent(响应)事件 Activity和view只有dispatchTouchEvent(分发)onTouchEvent(响应)事件 因为View没有子View,所以不需要拦截事件。而ViewGroup里面可以包裹子View,所以通过onInterceptTouchEvent方法 在dispatchTouchEvent中调用super.dispatchTouchEvent有底层执行底层dispatchTouchEvent 没有底层执行本层的onTouchEvent响应事件 dispatchTouchEvent返回true则表示响应事件不上发 返回false继续上发执行顶层onTouchEvent
① 驱动层 -> Framework 层 : 用户触摸 , 或按键 后 , 事件在硬件中产生 , 从 硬件驱动层 , 传递到 Framework 层 ;
② WMS -> View 层 : WindowManagerService ( 简称 WMS ) 将事件传递到 View 层 ;
③ View 层内部 : 事件在 View 的容器及下层容器 / 组件 之间传递 ;
https://cloud.tencent.com/developer/article/1154110
伪代码: 单指操作下的:
// ViewGroup 的 dispatchTouchEvent public boolean dispatchTouchEvent(MotionEvent ev) { boolean consume = false; // DOWN 事件重置触摸状态 if (ev.getAction() == MotionEvent.ACTION_DOWN) { mFirstTouchTarget = null; } boolean intercept = onInterceptTouchEvent(ev); // 拦截事件 if (!intercept) { if (ev.getAction() == MotionEvent.ACTION_DOWN) { // 查找 mFirstTouchTarget for (View child : childs) { if (mFirstTouchTarget!=null&&child.pointInView(ev.getX(), ev.getY()) && child.dispatchTouchEvent(ev)) { // 初始化 mFirstTouchTarget 链表,并添加 child mFirstTouchTarget = new TouchTarget(child); break; } } } } if (intercept || mFirstTouchTarget == null) { consume = super.dispatchTouchEvent(ev); // 最终调用View.dispatchTouchEvent } else { consume = mFirstTouchTarget.child.dispatchTouchEvent(ev); // 分发给 mFirstTouchTarget } return consume; } // View 的 dispatchTouchEvent public boolean dispatchTouchEvent(MotionEvent ev) { boolean consume = false; if (this.mOnTouchListener != null) { consume = mOnTouchListener.onTouch(this, ev); } if (!consume) { consume = onTouchEvent(ev); } return consume; }
Activity
SuDreamer commentedon Apr 22, 2019
429329513wanting commentedon Apr 22, 2019
zwonb commentedon Apr 22, 2019
当点击的时候,会先调用顶级viewgroup的dispatchTouchEvent,如果顶级的viewgroup拦截了此事件(onInterceptTouchEvent返回true),则此事件序列由顶级viewgroup处理。如果顶级viewgroup设置setOnTouchListener,则会回调接口中的onTouch,此时顶级的viewgroup中的onTouchEvent不再回调,如果不设置setOnTouchListener则onTouchEvent会回调。如果顶级viewgroup设置setOnClickListener,则会回调接口中的onClick。如果顶级viewgroup不拦截事件,事件就会向下传递给他的子view,然后子view就会调用它的dispatchTouchEvent方法。
ADrunkenLiBai commentedon Apr 22, 2019
StefanShan commentedon Apr 22, 2019
1.触发过程:Activity->Window->DocerView->ViewGroup->View,View不触发再返回由父级处理依次向上推。
2.在每个阶段都要经过三个方法 dispatchTouchEvent(分发)、onInterceptTouchEvent(拦截)、onTouch(处理)
大体流程:
Activity中走了Window 的 dispatch,Window 的 dispatch 方法直接走了 DocerView 的 dispatch 方法,DocerView 又直接分发给了 ViewGroup,ViewGroup 中走的是 onInterce 判断是否拦截,拦截的话会走 onTouch 来处理,不拦截则继续下发给 View。到 View 这里已经是最底层了,View 若继续不处理,那就调用上层的 onTouch 处理,上层不处理继续往上推。
推荐一篇介绍非常详细的博客:https://www.jianshu.com/p/38015afcdb58
MoJieBlog commentedon Apr 22, 2019
给大家举个形象的例子吧。ViewGroup相当于老板或者部门管理。View相当于员工。onTouchEvent相当于接业务。dispatechTouchEvent相当于处理任务。onIterceptTouchEvent相当于拦截任务。
先来分配角色
现在模拟来业务了(点击事件)
老板(ViewGroup)接到业务(onTouchEvent),他有两个选择
然后X部门领导接到任务,部门管理者有两个选择
领导接到员工的反馈,告诉老板(return true|renturn false)。
futureyang commentedon Apr 22, 2019
责任链模式
18361237136 commentedon Apr 22, 2019
qianxin2016 commentedon Apr 22, 2019
事件来源:input -> window -> ViewRoot -> DecorView -> Activity -> ...
事件处理:责任链模式,先从顶层传到底层,再从底层传回顶层,如果中间被消费或拦截,则流程结束
从Activity.dispatchTouchEvent()开始
--向下--> ViewGroup.dispatchTouchEvent(),可通过onInterceptTouchEvent()拦截
--向下--> View.dispatchTouchEvent()
--向下--> View.onTouchEvent()
--向上--> ViewGroup.onTouchEvent()
--向上--> Activity.onTouchEvent()
注意点:如果View没有消费ACTION_DOWN,后面的其他事件就不会再传过来
Techvisionbest commentedon Apr 24, 2019
View是没有onInterceptTouchEvent(拦截)的方法的
maoqitian commentedon Apr 25, 2019
之前写过一篇文章回顾时间分发机制,希望能有补充。
深入理解Android事件分发机制
chenqi5256969 commentedon May 5, 2019
1.当我们按下手指,ViewGroup的onInterceptTouchEvent会最先处理down事件。
假设1:onInterceptTouchEvent返回false,子view的onTouchEvent返回true,后续的move和up事件都将传到onInterceptTouchEvent中,然后一层一层的传递下去交给子view处理
假设2:onInterceptTouchEvent返回false,子view的onTouchEvent返回的是false,则后续的move和up事件都将交给ViewGroup的onTouchEvent处理,如果ViewGroup的onTouchEvent返回为true,ViewGroup将会自己处理,如果ViewGroup的onTouchEvent返回false,则会继续向上传递,交给ViewGroup的父亲来处理。
假设3:onInterceptTouchEvent返回true,那么down和后续的move和up事件将会交给ViewGroup的onTouchEvent处理
devzhan commentedon Apr 26, 2020
当顶级的ViewGroup接收到事件消息之后,会调用dispatchTouchEvent 方法进行分发事件,
在分发时会先去判断该事件是否拦截onInterceptTouchEvent。如拦截,则事件不继续进行
分发,自己进行消费。如不拦截,事件继续进行向下传递到子控件,如果子控件是ViewGroup
则继续走上述操作,如果是View则会走onTouchEvent方法。
其中ViewGroup不拦截之后会先走onTouch方法,该方法会影响其onTouchEvent。整体传递是一个责任链模式
qweenhool commentedon Aug 28, 2021
事件分发的细节真的非常多,用老板员工的例子,最早开始看的时候我是没记住过。如果你只是看别人得出来的结论,那么十个人他能总结出十种自己的结论,看似好像明白了,过一段时间自己去看还是会忘记,所以我觉得想要真的明白就得自己去跟踪源码,然后用关键代码提炼成伪代码,打log看结果,做好笔记。由于你没法获得自己手机的系统源码,所以最好用模拟器来调试,用模拟器对应的sdk版本编译运行代码,自定义几个简单的View和ViewGroup,从ViewGroup的dispatchTouchEvent()方法处开始打断点。这里分享一个小技巧,如果你想要程序在执行到你自定义ViewGroup的dispatchTouchEvent()处暂停,可以在断点的condition处加上this.getClass().getSimpleName().equals("CustomViewGroup1");这样的条件语句。后续总结完毕,我会发文章出来给大家参考的,大家有问题可以互相交流,共同进步。
mlinqirong commentedon Dec 17, 2021
事件分发机制是责任链模式,先从顶层传到底层,再从底层传回顶层,如果中间被消费或拦截,则流程结束:
Activity dispatchTouchEvent- >ViewGroup dispatchTouchEvent ->ViewGroup onInterceptTouchEventview->View dispatchTouchEvent -> ->View onTouchEvent-> ViewGroup onTouchEvent->Activity onTouchEvent
事件监听分别有
dispatchTouchEvent(分发)onInterceptTouchEvent(拦截)onTouchEvent(响应)事件
Activity和view只有dispatchTouchEvent(分发)onTouchEvent(响应)事件
因为View没有子View,所以不需要拦截事件。而ViewGroup里面可以包裹子View,所以通过onInterceptTouchEvent方法
在dispatchTouchEvent中调用super.dispatchTouchEvent有底层执行底层dispatchTouchEvent 没有底层执行本层的onTouchEvent响应事件 dispatchTouchEvent返回true则表示响应事件不上发 返回false继续上发执行顶层onTouchEvent
yline commentedon Sep 1, 2023
① 驱动层 -> Framework 层 : 用户触摸 , 或按键 后 , 事件在硬件中产生 , 从 硬件驱动层 , 传递到 Framework 层 ;
② WMS -> View 层 : WindowManagerService ( 简称 WMS ) 将事件传递到 View 层 ;
③ View 层内部 : 事件在 View 的容器及下层容器 / 组件 之间传递 ;
https://cloud.tencent.com/developer/article/1154110
flyisme commentedon Jun 20, 2024
伪代码: 单指操作下的: