Android进阶——Android事件分发机制之dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent
Android的事件分发
Android的事件分发一、Touch事件和绘制事件的异同之处Touch事件和绘制事件很类似,都是由ViewRoot派发下来的,但是不同之处在绘制事件是由应用中的某个View发起请求,一层一层上传到ViewRoot,再有ViewRoot下发绘制,传递canvas给所有子View让其绘制自身,绘制好后,再通知WMS进行画到屏幕上。
而Touch 事件是由硬件捕获到触摸后由系统传递给应用的ViewRoot,再由ViewRoot往下一层一层传递。
他们的处理过程都是自上而下的分发,但是绘制多了一层自下往上的请求。
事件存在消耗,事件的处理方法都会返回一个boolean值,如果该值为true,则本次事件下发将会终止。
二、MotionEvent1、MotionEvent对象的产生系统有一个线程在循环收集屏幕硬件信息,当用户触摸屏幕时,该线程会把从硬件设备收集到的信息封装成一个MotionEvent对象,然后把该对象存放到一个消息队列中。
系统的另一个线程循环的读取消息队列中的MotionEvent,然后交给WMS去派发,WMS 把该事件派发给当前处于活动的Activity,即处于活动栈最顶端的Activity。
这就是一个先进先出的消费者和生产者的模板,一个线程不停的创建MotionEvent对象放入队列中,另一个线程不断的从队列中取出MotionEvent对象进行分发。
当用户的手指从接触屏幕到离开屏幕,是一个完整的触摸事件,在该事件中,系统会不断收集事件信息封装成MotionEvent对象。
收集的间隔时间取决于硬件设备,例如屏幕的灵敏度以及cpu的计算能力。
目前的手机一般在20毫秒左右。
MotionEventCompat.getActionMasked()2、MotionEvent对象详解MotionEvent对象包含了触摸事件的时间、位置、面积、压力、以及本次事件的Dwon发生的时间。
MotionEvent常用的Action分为5种:Down 、Up、Move、Cancel、OutSideMotionEvent中我们常用的方法就是获取点击的坐标,因为这是与我们操作息息相关的。
Android触摸事件传递机制
一、了解Activity的构成一个Activity包含了一个Window对象,这个对象是由PhoneWindow来实现的。
PhoneWindow将DecorView作为整个应用窗口的根View,而这个DecorView又将屏幕划分为两个区域:一个是TitleView,另一个是ContentView,而我们平时所写的就是展示在ContentView中的,下图表示Activity的构成。
二、触摸事件的类型触摸事件对应的是MotionEvent类,事件的类型主要有如下三种:•ACTION_DOWN•ACTION_MOVE(移动的距离超过一定的阈值会被判定为ACTION_MOVE操作) •ACTION_UP三、事件传递的三个阶段•分发(dispatchTouchEvent):方法返回值为true表示事件被当前视图消费掉;返回为super.dispatchTouchEvent表示继续分发该事件。
•拦截(onInterceptTouchEvent):方法返回值为true表示拦截这个事件并交由自身的onTouchEvent方法进行消费;返回false表示不拦截,需要继续传递给子视图。
如果return super.onInterceptTouchEvent(ev),事件拦截分两种情况:1.如果该View(ViewGroup)存在子View且点击到了该子View, 则不拦截, 继续分发给子View 处理, 此时相当于return false。
2.如果该View(ViewGroup)没有子View或者有子View但是没有点击中子View(此时ViewGroup 相当于普通View), 则交由该View的onTouchEvent响应,此时相当于return true。
注意:一般的LinearLayout、 RelativeLayout、FrameLayout等ViewGroup默认不拦截,而ScrollView、ListView等ViewGroup则可能拦截,得看具体情况。
android知识点
Android 编程下Touch 事件的分发和消费机制Android 中与Touch 事件相关的方法包括:dispatchTouchEvent(MotionEvent ev)、onInterceptTouchEvent(MotionEvent ev)、onTouchEvent(MotionEvent ev);能够响应这些方法的控件包括:ViewGroup、View、Activity。
方法与控件的对应关系如下表所示:从这张表中我们可以看到ViewGroup 和View 对与Touch 事件相关的三个方法均能响应,而Activity 对 onInterceptTouchEvent(MotionEvent ev) 也就是事件拦截不进行响应。
另外需要注意的是View 对 dispatchTouchEvent(MotionEvent ev) 和 onInterceptTouchEvent(MotionEvent ev) 的响应的前提是可以向该View 中添加子View,如果当前的View 已经是一个最小的单元View(比如TextView),那么就无法向这个最小View 中添加子View,也就无法向子View 进行事件的分发和拦截,所以它没有 dispatchTouchEvent(MotionEvent ev) 和 onInterceptTouchEvent(MotionEvent ev),只有onTouchEvent(MotionEvent ev)。
一、Touch 事件分析▐事件分发:public boolean dispatchTouchEvent(MotionEvent ev)Touch 事件发生时 Activity 的 dispatchTouchEvent(MotionEvent ev) 方法会以隧道方式(从根元素依次往下传递直到最内层子元素或在中间某一元素中由于某一条件停止传递)将事件传递给最外层View 的dispatchTouchEvent(MotionEvent ev) 方法,并由该View 的dispatchTouchEvent(MotionEvent ev) 方法对事件进行分发。
Android事件分发机制-------View
Android事件分发机制-------View当触摸一个View时,首先会调用View的dispatchTouchEvent(MotionEvent event)方法,关乎着事件的分发,所以首先看看这个方法[java] view plain copy 在CODE上查看代码片派生到我的代码片public boolean dispatchTouchEvent(MotionEvent event) {// If the event should be handled by accessibility focus first.if (event.isTargetAccessibilityFocus()) {// We don't have focus or no virtual descendant has it, do not handle the event.if (!isAccessibilityFocusedViewOrHost()) {return false;}// We have focus and got the event, then use normal event dispatch.event.setTargetAccessibilityFocus(false);}boolean result = false;if (mInputEventConsistencyVerifier != null) {mInputEventConsistencyVerifier.onTouchEvent(event, 0);}final int actionMasked = event.getActionMasked();if (actionMasked == MotionEvent.ACTION_DOWN) {// Defensive cleanup for new gesturestopNestedScroll();}if (onFilterTouchEventForSecurity(event)) {//noinspection SimplifiableIfStatementListenerInfo li = mListenerInfo;if (li != null && li.mOnTouchListener != null&& (mViewFlags & ENABLED_MASK) == ENABLED&& li.mOnTouchListener.onTouch(this, event)) {result = true;}if (!result && onTouchEvent(event)) {result = true;}}if (!result && mInputEventConsistencyVerifier != null) {mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);}// Clean up after nested scrolls if this is the end of a gesture;// also cancel it if we tried an ACTION_DOWN but we didn't want the rest// of the gesture.if (actionMasked == MotionEvent.ACTION_UP ||actionMasked == MotionEvent.ACTION_CANCEL ||(actionMasked == MotionEvent.ACTION_DOWN && !result)) {stopNestedScroll();}return result;}看关键性的代码,包含了四个判断li:是ListenerInfo,点进去可以看到是各种Listener,OnFocusChangeListener,OnScrollChangeListener,OnClickListener等等。
Android 触摸事件的传递机制学习笔记
Android 触摸事件的传递机制学习笔记一. 触摸事件的类型触摸事件对应的是 MotionEvent,主要的事件有一下三种:1. ACTION_DOWN手指的按下动作;一次ACTION_DOWN,标志着一个触摸事件的开始。
2. ACTION_UP手指离开屏幕的动作;一次 ACTION_UP,标志着一个触摸事件的结束。
3. ACTION_MOVE手指按压屏幕并且移动一定的距离;手指的轻微移动会触发一系列的 ACTION_MOVE 事件。
二. 触摸事件传递的三个阶段1. 分发 (Dispatch)事件的分发对应着dispatchTouchEvent方法,Android 系统中的所有的事件都是通过该方法来分发的。
方法原型如下:public void dispatchTouchEvent(MotionEvent event);返回值说明:true:表示触摸事件被当前视图消费,不再继续分发该事件。
super.dispatchTouchEvent:表示继续分发该事件,如果当前视图是 ViewGroup 或其子类,则由onInterceptTouchEvent决定是否拦截该事件。
2. 拦截 (Intercept)触摸事件的拦截对应着onInterceptTouchEvent方法,该方法只在 ViewGroup 或子类中存在,Activity 和 View 中没有。
方法原型:public boolean onInterceptTouchEvent(MotionEvent event);返回值说明true:表示拦截该事件,不再继续向子视图分发该事件,同时交由该视图的的onTouchEvent方法进行消费。
false | super.onInterceptTouchEvent:表示不对触摸事件进行拦截,需要继续分发给子视图进行处理。
3. 消费 (Consume)触摸事件的消费对应着onTouchEvent方法。
方法原型如下:public boolean onTouchEvent(MotionEvent event);返回值说明true:表示该视图可以处理对应的触摸事件,事件将不会向上传递给父视图。
Android中触摸事件传递分发机制
Android中触摸事件传递分发机制触摸事件用MotionEvent表示,在Android中,一个触摸事件从产生到最终起作用,是一个很复杂的过程,但思路还是很清晰的,就是一层一层的传递,通过一个boolean值判断是否拦截或者消耗(也就是使用掉这个事件)。
下面从基础的事件产生过程开始梳理整个流程:事件的类型:一般使用手机,在屏幕上的操作就是点击或滑动,所以一般触摸事件分为两类:•点击事件:ACTION_DOWN–>ACTION_UP•滑动事件:ACTION_DOWN–>ACTION_MOVE–>ACTION_MOVE … … –>ACTION_UP可以看到,事件的开始都是ACTION_DOWN,结束是ACTION_UP。
滑动事件相比点击事件,多了n个ACTION_MOVE事件,也就是滑动过程中手指与屏幕的交互,其他就没什么区别了。
事件的传递过程:在Android中,Activity作为界面显示的基础,通常用来接收触摸事件,然后分发给界面中的视图控件。
当一个触摸事件产生时,最先传递给当前Activity,然后由Activity内部的Window将事件传递给DecorView(也就是当前屏幕显示的界面的底层容器)接下来就是在开发者编写的ViewGroup和View中传递了,所以整理下事件传递过程如下图:从图中可以看到,由于DecorView继承自FrameLayout,所以它是一个ViewGroup,ContentView也是一个ViewGroup,因此,整个传递过程可以简化为三个步骤:Activity—->ViewGroup…—->View也就是从Activity传递到ViewGroup,再经过n步的ViewGroup 之间传递,最终传递给View。
事件传递的代码实现:将以上传递规则通过代码实现,主要涉及到以下三个方法:•dispatchTouchEvent():分发触摸事件,默认返回super.dispatchTouchEvent(ev),事件向上分发。
Android事件分发机制
Android事件分发机制【注】:这篇文章中的内容都以这张图来讲解分发机制,其中A、B、C都是ViewGroup,它们的层次关系为:A为根布局,B为二级子布局,C为三级子布局,其中C布局中包含一个Button按钮,即A包含B,B包含C,C包含Button。
好了,废话少说。
先来讲下今天的三位主角吧。
1、dispatchTouchEvent - 分发事件,默认为false。
true:取消事件,不继续向下分发,false:向下分发事件2、onInterceptTouchEvent - 拦截事件,默认为false。
true:拦截事件,自身的onTouchEvent()方法消费,false:事件继续向下传递3、onTouchEvent - 处理事件,默认为false,true:消费事件,false:不消费事件,向上层传递让上层处理。
【注】如果发生了拦截,那么如果该层不处理则会继续向上传递,让上层处理。
如果过程中没有发生处理,则事件分发到底层后将一直向上层传递至Activity,在Activity的onTouchEvent()中处理。
【注】如果在设置了setOnClickListener(…)的View 或Viewgroup中,返回true则消费事件,会触发onClick事件,如果返回false,则不会触发onClick事件这里借用网上的两张图片来增加理解:1、在没有做任何处理,也即默认情况下,触摸屏幕发生的一系列事件分发过程:如果DOWN事件没有被消费,则后续的MOVE/UP事件将不会传递过来,直接在Activity层处理2、如果子View消费了事件,则事件的分发过程为:上面这三个方法就是负责Android中当用户触摸屏幕时事件的分发与处理。
在Android中,事件的分发是遵循这样一套机制的:当用户触摸到屏幕时,也就是触摸到Activity界面,当Activity中的dispatchTouchEvent()方法允许分发时,这时这个触摸事件就会先出现在根布局这个ViewGroup中,然后再向里层的ViewGroup或View传递,也就是Activity->RootView->子ViewGroup->…..->View。
android事件分发理解
android事件分发理解Android事件分发是指在Android系统中,当用户触摸屏幕或执行其他操作时,系统如何将这些事件传递给应用程序的过程。
事件分发涉及多个层级,包括Activity、ViewGroup和View。
首先,事件从顶级的Activity开始,通过Activity的dispatchTouchEvent()方法进行处理。
该方法会将事件传递给当前显示的根布局ViewGroup。
接下来,ViewGroup会调用自己的dispatchTouchEvent()方法,该方法会遍历它的所有子View,并依次调用它们的dispatchTouchEvent()方法。
这个过程是递归的,直到事件传递到最底层的View。
在View的dispatchTouchEvent()方法中,会先判断事件的类型(如触摸、滑动、点击等),然后根据事件类型调用对应的回调方法(如onTouchEvent()、onScroll()、onClick()等)来处理事件。
在事件的处理过程中,每个View都有机会消费事件,即决定是否处理该事件。
如果View消费了事件,那么事件将不再向下传递给其他View。
如果View不消费事件,那么事件将继续向上传递给父View,直到被消费或传递到顶级的Activity。
此外,Android还提供了事件拦截的机制,即通过重写ViewGroup的onInterceptTouchEvent()方法来拦截事件。
当某个ViewGroup拦截了事件后,该事件将直接传递给该ViewGroup的onTouchEvent()方法进行处理,而不再向下传递给子View。
总结来说,Android事件分发是一个层级结构,从Activity到ViewGroup再到View,通过dispatchTouchEvent()方法和onTouchEvent()等回调方法来传递和处理事件。
每个View都有机会消费事件,而ViewGroup还可以拦截事件。
Android事件传递机制
Android事件传递机制Android事件传递机制AndroidonInterceptTouchEvenonTouchEvent事件处理dispatchTouchEventAndroid中dispatchTouchEvent,onInterceptTouchEvent, onTouchEvent的理解android中的事件类型分为按键事件和屏幕触摸事件,Touch事件是屏幕触摸事件的基础事件,有必要对它进⾏深⼊的了解。
⼀个最简单的屏幕触摸动作触发了⼀系列Touch事件:ACTION_DOWN->ACTION_MOVE->ACTION_MOVE->ACTION_MOVE...->ACTION_MOVE->ACTION_UPandroid的事件处理分为3步。
1)public booleandispatchTouchEvent(MotionEvent ev) 这个⽅法⽤来分发TouchEvent2)public boolean onInterceptTouchEvent(MotionEvent ev) 这个⽅法⽤来拦截TouchEvent 3)public boolean onTouchEvent(MotionEvent ev) 这个⽅法⽤来处理TouchEvent假设当前Activity 布局如下:dispatchTouchEvent事件分发当TouchEvent发⽣时,⾸先Activity将TouchEvent传递给最顶层的View, TouchEvent最先到达最顶层 view 的 dispatchTouchEvent 。
然后由 dispatchTouchEvent ⽅法进⾏分发,如果dispatchTouchEvent返回true ,则交给这个view的onTouchEvent处理,如果dispatchTouchEvent返回 false ,则交给这个 view 的 onInterceptTouchEvent⽅法来决定是否要拦截这个事件,如果onInterceptTouchEvent返回 true ,也就是拦截掉了,则交给它的 onTouchEvent 来处理,如果onInterceptTouchEvent返回 false ,那么就传递给⼦ view,由⼦ view 的dispatchTouchEvent 再来开始这个事件的分发。
【IT专家】深入聊聊Android事件分发机制
本文由我司收集整编,推荐下载,如有疑问,请与我司联系深入聊聊Android 事件分发机制2017/02/09 38100 在Android 开发的过程中,自定义控件一直是我们绕不开的话题。
而在这个话题中事件分发机制也是其中的重点和疑点,特别是当我们处理控件嵌套滑动事件时,正确的处理各个控件间事件分发拦截状态,可以实现更炫酷的控件动画效果。
一、事件分发机制介绍关于Android 事件分发,我们主要分ViewGroup 和View两个事件处理部分进行介绍,主要研究在处理事件过程中关注最多的三个方法dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent,在ViewGroup 和View 对三个方法的支持如下图所示:在Android 中,当用户触摸界面时系统会把产生一系列的MotionEvent,通过ViewGroup 的dispatchTouchEvent 方法开始向下分发事件,在dispatchTouchEvent方法中,会调用onInterceptTouchEvent 方法,如果该方法返回true,表明当前控件拦截了该事件,此后事件交由该控件处理并不再调用该控件的onInterceptTouchEvent 方法。
最后交由该控件的onTouchEvent 方法对事件进行处理。
如果当前控件在onInterceptTouchEvent 方法中返回false,表示不拦截该控件,之后交由其子控件进行判断是否对事件进行拦截处理。
可以用如下伪代码来对其进行处理:public boolean dispatchTouchEvent(MotionEvent event) { boolean consume = false; if (onInterceptTouchEvent(event)) { consume = onTouchEvent(event); } else { consume = child.dispatchTouchEvent(event); } return consume; }先说结论再细分析:事件是由其父视图向子视图传递,如图为A- B- C 如果当前控件需要拦截该事件,则在onInterceptTouchEvent 方法中返回true,但真正决定是否处理事件是在onTouchEvent 方法中,也就是说如果此时onTouchEvent 方法返回了false,则此控件也表示不处理该事件,交由父控件的onTouchEvent 方法来判断处理。
Androidtouch事件传递机制
Androidtouch事件传递机制前⾔:(1)在⾃定义view的时候经常会遇到事件拦截处理,⽐如在侧滑菜单的时候,我们希望在侧滑菜单⾥⾯有listview控件,但是我们希望既能左右滑动⼜能上下滑动,这个时候就需要对触摸的touch事件进⾏拦截。
这个时候我们就需要明⽩android touch 事件传递机制,(2)以前很多时候⽐较模糊,也许是⽹上看到也有很多事件传递的相关⽂章,但我看着头晕,解释不彻底,有的说得⼀半,总算不满⾜不满意,于是据我⾃⼰的理解来彻底的来整理下具体的是怎么个传递⽅式,以最简单通俗易懂的⽅式分享给⼤家,希望⼤家看到有什么不对的地⽅及时提出纠正。
谢谢测试布局:这是本次理解android touch 事件传递机制的布局⽂件传递机制视图:(1)android touch 事件传递机制⽰意图,由于⽹页原因会被拉伸,请⼤家单独将该图在另⼀个窗⼝打开查看。
(2)事件是从Activity触发事件然后传递到布局⽂件,⼀层⼀层的往⼦容器传递到最底层的view,如果每层布局⽂件未对该事件进⾏处理或者消费那么该事件会从最底层开始往上传到Activity进⾏消费。
类似于⼀个U型。
(3)那么事件的发起是由Activity界⾯的touch事件发起传递到布局视图,但是该视图只是描述了布局⽂件或者view的相关事件传递机制,Activity事件没有进⾏描述,但是在下⾯测试中会涉及Activity相关事件传递来解释⼼中些许疑惑事件传递另⼀个⾓度解释:android touch 事件传递机制⽰意图可以总结如下规律(0)忘掉以前的各种说法解释,因为各种组合说来说去的,我们需要简单的,换⼀个⾓度,换⼀个思维,忘记事件传递,以最简单通俗易懂的⽅式理解事件传递,我只需要⼀张图就搞定事件传递机制。
(1)⼀个事件由⽤户点击触发开始顺着箭头的⽅向进⾏传递,直到任意⼀个结束点结束事件传递。
(2)那么事件传递可以由A传到B,B可以不传到C,B不进⾏分发,那么就从B再传回A进⾏消费然后结束,也可以由B传到C然后传递D,或者不传到D进⾏消费或者传到⽗容器进⾏消费结束。
【推荐下载】Android学习第六弹之Touch事件的处理
Android 学习第六弹之Touch 事件的处理2015/08/06 0 在移动开发过程当中,我们经常会遇到手势处理和事件触摸的情况,如果不了解整个事件的处理机制,对于开发的同学和码农是非常痛苦的,但是事件触摸的处理确实是一个非常复杂的过程,细讲起来,估计我都能讲迷糊,这里呢,我只做一些简单的和常用事件的讲解,希望能够帮助大家。
1.概念,什么是事件的派发事件的派发简单来讲就是Activity 将事件派发给容器和控件,容器或控件将事件进一步派发给其子容器和子控件,直到事件最终派发到事件发生的焦点控件上。
2.常用的事件触摸方法我想对于这些常用的事件触摸方法大家都应该有一定的了解,或者熟悉,那就是onTouchEvent()和dispatchTouchEvent(),OnInterceptTouchEvent(),看到方法后,相信你很快就会说,对我用过,但是具体的意思没有搞清楚,看别人这么说的,别人这么用的,我就跟着这么用的,用之前,对于这些方法我们一定要搞清其作用,这样才能在做起来有的放矢。
现在我们就来介绍一下这三种方法的大概用法和作用。
①、Boolean onTouchEvent()作用:处理本次触摸事件。
解释:如果某个控件或容器消费了touch 事件,则与该touch 事件相关的后续touch 事件者会派发给该控件或容器进行处理。
返回:该方法的返回机理与键盘响应事件的相同,同样是当已经完整地处理了该事件且不希望其他回调方法再次处理时返回true,否则返回false。
一般情况下以下三种情况的事件全部由onTouchEvent 方法处理,只是三种情况中的动作不同。
屏幕被按下:当屏幕被按下时,会自动调用该方法来处理事件,此时MotionEvent.getAction()的为MotionEvent.ACTION_DOWN,如果在应用程序中需要处理屏幕被按下的事件,只需重新该回调方法,然后在方法中进行动作的判断即可。
安卓中touch事件传递机制
Android Touch事件传递机制解析没事逛论坛,无意间看到了一篇非常不错的帖子,转载如下:开篇语:最近程序在做一个小效果,要用到touch,结果整得云里面雾里的,干脆就好好把android touch机制好好看了一下,呵呵。
android系统中的每个ViewGroup的子类都具有下面三个和TouchEvent处理密切相关的方法:1)public boolean dispatchTouchEvent(MotionEvent ev) 这个方法用来分发TouchEvent2)public boolean onInterceptTouchEvent(MotionEvent ev) 这个方法用来拦截TouchEvent3)public boolean onTouchEvent(MotionEvent ev) 这个方法用来处理TouchEvent注意:不是所有的View的子类,很多教程都说的是所有的View的子类,只有可以向里面添加View的控件才需要分发,比如TextView它本身就是最小的view了,所以不用再向它的子视图分发了,它也没有子视图了,所以它没有dispatch和Intercept,只有touchEvent。
说明:白色为最外层,它占满整个屏幕;红色为中间区域,属于白色中的一层;黑色为中心区域,必于红色中的一层。
注意:他们本质上是:LinearLayout,而不是RelativeLayout或者其它布局。
1.由中心区域处理touch事件布局文件如下:1.<?xml version="1.0" encoding="utf-8"?>2.<LinearLayoutxmlns:android="/apk/res/android"3.android:layout_width="fill_parent"4.android:layout_height="fill_parent"5.android:orientation="vertical">6.<com.kris.touch.widget.TouchView7.android:id="@+id/view_out"8.android:layout_width="fill_parent"9.android:layout_height="fill_parent"10.android:background="#fff"11.android:gravity="center">12.<com.kris.touch.widget.TouchView13.android:id="@+id/view_mid"14.android:layout_width="300px"15.android:layout_height="400px"16.android:background="#f00"17.android:gravity="center">18.<com.kris.touch.widget.TouchView19.android:id="@+id/view_center"20.android:layout_width="150px"21.android:layout_height="150px"22.android:background="#000"23.android:gravity="center"24.android:clickable="true">25.</com.kris.touch.widget.TouchView>26.</com.kris.touch.widget.TouchView>27.</com.kris.touch.widget.TouchView>28.</LinearLayout>复制代码注意:android:clickable="true"接下来我们看一下打印的日志:结合是上面的日志,我们可以看一下ACTION_DOWN事件处理流程:说明:首先触摸事件发生时(ACTION_DOWN),由系统调用Activity的dispatchTouchEvent 方法,分发该事件。
android事件分发机制 简单完整总结
android事件分发机制简单完整总结
Android事件分发机制是指在Android系统中,如何将触摸事件或其他类型的事件传递给合适的View进行处理的过程。
它主要包括三个层级:顶层的Activity/Window、中间层的ViewGroup、底层的View。
简单来说,Android的事件分发机制遵循以下步骤:
1. 用户在屏幕上触发一个事件,比如点击、滑动等等。
2. 事件首先通过Activity的dispatchTouchEvent()方法进行处理。
3. Activity会将事件交给顶层的Window进行处理,在Window内部会创建一个DecorView来接收触摸事件。
4. DecorView会将事件传递给根布局ViewGroup进行处理。
5. 根布局ViewGroup会递归遍历所有的子View,通过调用每个子View的dispatchTouchEvent()方法,依次传递触摸事件。
6. 如果某个子View消费了事件(返回true),那么事件传递就终止,其它子View将不再收到事件。
7. 如果没有子View能够消费事件,或者所有子View都返回false,那么事件会继续向上传递给父ViewGroup。
8. 如果根布局ViewGroup也无法消费事件(所有子View都返回false),那么最终事件会传递给Activity的onTouchEvent()方法进行处理。
总结起来,Android的事件分发机制是一个从顶层到底层的逐层传递的过程,每个层级都有机会处理事件,通过返回值来判断是否消费
事件。
这样设计可以灵活地处理各种不同的事件,同时将事件分发和处理的责任分担给了不同的组件,提高了系统的灵活性和性能。
Android事件分发机制简述
下面说一下这之间的作用关系:
1.onInteceptTouchEvent,返回boolean,false表示不拦截事件 事件传递到下一级view
以上是我的理解感觉这么解释更好理解说的不对的地方欢迎留言指正
Android事 件 分 发 机 制 简 述
android的事件分发机制有两个主角:View、ViewGroup ViewGroup包含View,作为孩子的View又可以作为ViewGroup包含下一级View…… ViewGroup有三个事件:onInteceptTouchEvent、dispatchTouchEvent、onTouchEvent
2.dispatchTouchEvent ,返回boolean。 true: 表示不往下分发,又自己处理,然后执行onTouchEvent来处理事件(PS:dispatchTouchEvent本 身不处理事件); false: 分发事件 事件传递到下一级view
3.onTouc
Android触摸事件传递机制
Android触摸事件传递机制前⾔:在Android开发中,经常会遇到触摸事件冲突,⽐如ViewPager的轮播图跟Fragment的划动事件冲突,或者轮播图跟下拉事件冲突,⾃定义view的事件处理等,本⽂章将会详细介绍Activity、View、ViewGroup三者的触摸事件传递机制,传递包括三个阶段:分发、拦截、消费。
本⽂章将会详细介绍Activity、View、ViewGroup三者的触摸事件传递机制,传递包括三个阶段:分发、拦截、消费。
⼀.触摸事件的类型触摸事件对应的是 MotionEvent 类,事件类型主要有三种:1. ACTION_DOWN:⽤户按下操作,表⽰⼀次触摸事件的开始。
2. ACTION_MOVE:在按下的情况下,进⾏移动。
轻微的移动都会传递到该事件。
3. ACTION_UP:⽤户⼿指离开屏幕,表⽰⼀次触摸事件的注:如果⽤户仅仅的是点击⽽已,则只会执⾏到 ACTION_DOWN 和 ACTION_UP 两个事件,不会执⾏到 ACTION_MOVE 事件。
所以 ACTION_DOWN 和 ACTION_UP 是事件是必须的。
⼆.触摸事件的传递阶段1.分发(Dispatch)在Android系统中所有的触摸事件都是由 dispatchTouchEvent ⽅法进⾏分发的。
该⽅法中判断事件是被消费( return true ),还是继续分发给⼦视图处理( return super.dispatchTouchEvent ),如果当前视图是ViewGroup或者其⼦类,则会调⽤onInterceptTouchEvent 判断是否截拦。
@Overridepublic boolean dispatchTouchEvent(MotionEvent event) {return super.dispatchTouchEvent(event);}2.截拦(Intercept)事件的截拦 InterceptTouchEvent 只存在于ViewGroup及其⼦类,activity和View是不存在该⽅法。
Android事件分发机制个人总结
Android事件分发机制个⼈总结
前⾔:关于Android点击事件的分发机制的详解在我转载的上篇⽂章就能看到,很全⾯也很详细。
但是由于篇幅也过于长了,想要完全了解需要⼀定的时间,于是⾃⼰便制作了⼏个流程图,算是⾃我的⼀个⼩总结。
事件分发机制的三个重要⽅法
1、dispatchTouchEvent(MotionEvent ev) —– ⽤于事件的分发。
2、onInterceptTouchEvent(MotionEvent ev) —– ⽤于事件的拦截,在dispatchTouchEvent()中调⽤,只有ViewGroup 中有该⽅
法。
3、onTouchEvent(MotionEvent ev) —– ⽤于处理点击事件,在dispatchTouchEvent()中调⽤。
事件分发的顺序
事件传递的顺序:Activity -> ViewGroup -> View
事件分发业务流程
Down后续事件流程
1、第⼀个Down事件传递
2、Cancel 事件传递
3、后续Move事件传递
⾄此,关于Android 事件分发机制的流程就完成了,想对分发机制有更深了解的可以看上⼀篇⽂章。
一文读懂AndroidTouchEvent事件分发、拦截、处理过程
⼀⽂读懂AndroidTouchEvent事件分发、拦截、处理过程什么是事件?事件是⽤户触摸⼿机屏幕,引起的⼀系列TouchEvent,包括ACTION_DOWN、ACTION_MOVE、ACTION_UP、ACTION_CANCEL等,这些action组合后变成点击事件、长按事件等。
在这篇⽂章中,⽤打Log测试的⽅法来了解Android TouchEvent 事件分发,拦截,处理过程。
虽然看了⼀些其他的⽂章和源码及相关的资料,但是还是觉得需要打下Log和画图来了解⼀下,不然很容易忘记了事件传递的整个过程。
所以写下这篇⽂章,达到看完这篇⽂章基本可以了解整个过程,并且可以⾃⼰画图画出来给别⼈看。
先看⼏个类,主要是画出⼀个3个ViewGroup叠加的界⾯,并在事件分发、拦截、处理时打下Log.⼀、通过打log分析事件分发这⾥在⼀个Activity上添加三个ViewGroup来分析,这⾥值得注意的是Activity、View是没有onInterceptTouchEvent⽅法的。
⼀、了解Activity、ViewGroup1、ViewGroup2、ViewGroup3四个类1. activity_main.xml<?xml version="1.0" encoding="utf-8"?><android.support.constraint.ConstraintLayout xmlns:android="/apk/res/android"xmlns:app="/apk/res-auto"xmlns:tools="/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context="com.touchevent.demo.MyActivity"><com.touchevent.demo.ViewGroup1android:layout_width="match_parent"android:layout_height="match_parent"android:background="@color/colorAccent"><com.touchevent.demo.ViewGroup2android:layout_width="match_parent"android:layout_height="match_parent"android:layout_margin="50dp"android:background="@color/colorPrimary"><com.touchevent.demo.ViewGroup3android:layout_width="match_parent"android:layout_height="match_parent"android:layout_margin="50dp"android:background="@color/colorPrimaryDark"></com.touchevent.demo.ViewGroup3></com.touchevent.demo.ViewGroup2></com.touchevent.demo.ViewGroup1></android.support.constraint.ConstraintLayout>2. 主界⾯:MainActivity.javapublic class MyActivity extends AppCompatActivity {private final static String TAG = MyActivity.class.getName();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(yout.activity_main);@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {Log.i(TAG, "dispatchTouchEvent action:" + StringUtils.getMotionEventName(ev));boolean superReturn = super.dispatchTouchEvent(ev);Log.d(TAG, "dispatchTouchEvent action:" + StringUtils.getMotionEventName(ev) + " " + superReturn);return superReturn;}@Overridepublic boolean onTouchEvent(MotionEvent ev) {Log.i(TAG, "onTouchEvent action:" + StringUtils.getMotionEventName(ev));boolean superReturn = super.onTouchEvent(ev);Log.d(TAG, "onTouchEvent action:" + StringUtils.getMotionEventName(ev) + " " + superReturn);return superReturn;}}3. 三个ViewGroup,⾥⾯的代码完全⼀样:ViewGroup1.java,ViewGroup2.java,ViewGroup3.java。
android事件分发机制的实现原理
android事件分发机制的实现原理android中的事件处理,以及解决滑动冲突问题都离不开事件分发机制,android中的事件流,即MotionEvent都会经历⼀个从分发,拦截到处理的⼀个过程。
即dispatchTouchEvent(),onInterceptEvent()到onTouchEvent()的⼀个过程,在dispatchTouchEvent()负责了事件的分发过程,在dispatchTouchEvent()中会调⽤onInterceptEvent()与onTouchEvent(),如果onInterceptEvent()返回true,那么会调⽤到当前view的onTouchEvent()⽅法,如果不拦截,事件就会下发到⼦view的dispatchTouchEvent()中进⾏同样的操作。
本⽂将带领⼤家从源码⾓度来分析android是如何进⾏事件分发的。
android中的事件分发流程最先从activity的dispatchTouchEvent()开始:public boolean dispatchTouchEvent(MotionEvent ev) {if (ev.getAction() == MotionEvent.ACTION_DOWN) {onUserInteraction();}if (getWidow().superDispatchTouchEvent(ev)) {return true;}return onTouchEvent(ev);}这⾥调⽤了getWindow().superDispatchTouchEvent(ev),这⾥可以看出activity将MotionEvent传寄给了Window。
⽽Window 是⼀个抽象类,superDispatchTouchEvent()也是⼀个抽象⽅法,这⾥⽤到的是window的⼦类phoneWindow。
@Overridepublic boolean superDispatchTouchEvent(MotionEvent event) {return mDecor.superDispatchTouchEvent(event);}从这⾥可以看出,event事件被传到了DecorView,也就是我们的顶层view.我们继续跟踪:public boolean superDispatchTouchEvent(MotionEvent event) {return super.dispatchTouchEvent(event);}这⾥调⽤到了⽗类的dispatchTouchEvent()⽅法,⽽DecorView是继承⾃FrameLayout,FrameLayout继承了ViewGroup,所以这⾥会调⽤到ViewGroup的dispatchTouchEvent()⽅法。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Android进阶——Android事件分发机制之dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent 前言Android事件分发机制可以说是我们Android工程师面试题中的必考题,弄懂它的原理是我们避不开的任务,所以长痛不如短痛,花点时间干掉他,废话不多说,开车啦Android事件分发机制的简介Android事件分发机制的发生在View与View之间或者ViewGroup与View之间具有镶嵌的视图上,而且视图上必须为点击可用。
当一个点击事件产生后,它的传递过程遵循如下顺序:Activity->Window->View,即事件先传递给Activity,再到Window,再到顶级View,才开始我们的事件分发Android事件分发机制的相关概念Android事件分发机制主要由三个重要的方法共同完成的dispatchTouchEvent:用于进行点击事件的分发onInterceptTouchEvent:用于进行点击事件的拦截onTouchEvent:用于处理点击事件这里需要注意的是View中是没有onInterceptTouchEvent()方法的Android事件分发机制的分发例子这里以两个ViewGroup嵌套View来演示,下面是演示图一、MyView继承View并覆写其三个构造方法,覆写dispatchTouchEvent和onTouchEvent,前面已经说了View是没有onInterceptTouchEvent方法的public class MyView extends View {public MyView(Context context) {super(context);}public MyView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}public MyView(Context context, AttributeSet attrs) {super(context, attrs);}@Overridepublic boolean dispatchTouchEvent(MotionEvent event) {System.out.println("MyView dispatchTouchEvent");return super.dispatchTouchEvent(event);}@Overridepublic boolean onTouchEvent(MotionEvent event) {System.out.println("MyView onTouchEvent");return super.onTouchEvent(event);}}二、MyViewGroup01和MyViewGroup02MyViewGroup01和MyViewGroup02是一样的代码,这里以01为例,继承ViewGroup并覆写其三个构造方法,覆写dispatchTouchEvent和onTouchEvent和onInterceptTouchEvent方法public class MyViewGroup01 extends LinearLayout {public MyViewGroup01(Context context) {super(context);}public MyViewGroup01(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr);}public MyViewGroup01(Context context, AttributeSet attrs) {super(context, attrs);}@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {System.out.println("MyViewGroup01 dispatchTouchEvent");return super.dispatchTouchEvent(ev);}@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {System.out.println("MyViewGroup01 onInterceptTouchEvent");return super.onInterceptTouchEvent(ev);}@Overridepublic boolean onTouchEvent(MotionEvent event) {System.out.println("MyViewGroup01 onTouchEvent");return super.onTouchEvent(event);}}三、MyView和MyViewGroup布局文件这里以ViewGroup和Group嵌套,由上面可以知道事件最后分配到布局的顶级View,这里的顶级View是MyViewGroup02,然后开始事件的传递<?xml version="1.0" encoding="utf-8"?><com.handsome.boke2.TouchEvent.MyViewGroup02xmlns:android="/apk/res/android"android:layout_width="200dp"android:layout_height="200dp"android:background="#0f0"><com.handsome.boke2.TouchEvent.MyViewGroup01android:layout_width="100dp"android:layout_height="100dp"android:background="#f00"><com.handsome.boke2.TouchEvent.MyViewandroid:layout_width="50dp"android:layout_height="50dp"android:background="#00f" /></com.handsome.boke2.TouchEvent.MyViewGroup01></com.handsome.boke2.TouchEvent.MyViewGroup02>四、分析事件传递点击MyView(即蓝色部分):其事件会从顶级View(MyViewGroup02)往下分发,而事件的分发过程中分为两步骤分发过程处理过程其正常的分发事件结果为//分发过程MyViewGroup02 dispatchTouchEventMyViewGroup02 onInterceptTouchEventMyViewGroup01 dispatchTouchEventMyViewGroup01 onInterceptTouchEventMyView dispatchTouchEvent//处理过程MyView onTouchEventMyViewGroup01 onTouchEventMyViewGroup02 onTouchEvent1、dispatchTouchEvent(分发事件)如果在MyViewGroup01的dispatchTouchEvent方法中返回true,表示需要在MyViewGroup01消费了整个事件,即不会再分发,也不会再处理。
dispatchTouchEvent方法中返回true的打印信息//分发过程MyViewGroup02 dispatchTouchEventMyViewGroup02 onInterceptTouchEventMyViewGroup01 dispatchTouchEvent如果在MyViewGroup01的dispatchTouchEvent方法中返回false,表示在MyViewGroup01点击事件在本层不再继续进行分发,并交由上层控件的onTouchEvent方法进行消费。
dispatchTouchEvent方法中返回false的打印信息//分发过程MyViewGroup02 dispatchTouchEventMyViewGroup02 onInterceptTouchEventMyViewGroup01 dispatchTouchEvent//处理过程MyViewGroup02 onTouchEvent2、onInterceptTouchEvent(拦截事件)如果在MyViewGroup01的onInterceptTouchEvent方法中返回true,表示需要在MyViewGroup01拦截这个点击事件,不再继续往下分发,即MyView不再执行dispatchTouchEvent方法。
但是只是分发结束了而已,接着开始处理事件。
下面是onInterceptTouchEvent方法中返回true的打印信息//分发过程MyViewGroup02 dispatchTouchEventMyViewGroup02 onInterceptTouchEventMyViewGroup01 dispatchTouchEventMyViewGroup01 onInterceptTouchEvent//处理过程MyViewGroup01 onTouchEventMyViewGroup02 onTouchEvent如果在MyViewGroup01的onInterceptTouchEvent方法中返回false,表示需要在MyViewGroup01不会拦截这个点击事件,继续往下分发。
下面是onInterceptTouchEvent方法中返回false的打印信息//分发过程MyViewGroup02 dispatchTouchEventMyViewGroup02 onInterceptTouchEventMyViewGroup01 dispatchTouchEventMyViewGroup01 onInterceptTouchEventMyView dispatchTouchEvent//处理过程MyView onTouchEventMyViewGroup01 onTouchEventMyViewGroup02 onTouchEvent3、onTouchEvent(消费事件)如果MyViewGroup01的onTouchEvent方法中返回true,表示MyViewGroup01可以将该事件直接消费掉了,即分发结束后,处理事件的时候,直接处理到MyViewGroup01就可以结束了。