在view绘制完成后,要想在和view交互一定就要使用事件了,这些事件包括触屏,按键,以及轨迹球,说起轨迹球,在黑莓的手机上常见,现在触屏出来之后基本上就没有这个东西了。这些事件从屏幕上产生出来,会进行硬件中断,然后交给操作系统,然后由操作系统分发给我们的应用,我们就从frameworlk层开始分析。

首先是由windowmanagerservice接收到之后会使用共享内存和管道和我们的程序进行进程通讯,也就是ViewRoot之前就说过他是管理view的事件的。它存在windowmanager中,当Viewroot调用dispatchPointer方法调用diliverpointerevent就交给了mView的dispatchtouchevent。这个mView就是decorview。这时候decroview调用了一个回调函数的回调callback,这个callback是谁?如果还记得activity的挂载的,在actvity的attach的时候设置了回调就是activity。也就是说这里的回调实际上是activity的dispatchtouchevent。

这个时候开始就要开始事件的分发了,首先要知道一个规则:事件是由布局向下传递的,也就是说先在activity这一层,然后传递给decroview,然后在传递给各个布局。

在activity的dispatch中会传递给decroview的dispatchtouchevent,这时候假如传递下去没有处理,就说明这个事件没有被消费,处理函数都是返回了false。这时候才会交给activity的ontouchevent。这也就说明,虽然事件向下处理,但是是最子的view拥有最高的优先处理权,只有在最里面的view不处理,才会交给外层的布局处理,都不处理才会交给activity处理。

当传递给decroview的时候,就会传递给最外面的布局viewgroup处理,这时候就要说明viewgroup的处理流程了:

tip: 在说处理流程之前有必要说明一下触摸事件:其实触摸事件一般是连续的也就是说actiondown 之后会有actionmove然后有actionup,可能中间不会有actionmove,但是对应的要有actionup。这是一般,特殊情况就是actiondown之后是actioncancel。其实我们事件里没有actioncancel,这个出现是由于出现了actiondown,但是后续actionup一直没有,就比如移动出了view的范围,为了一个完整的动作处理就需要系统自动发一个actioncancel,和up作用是一样的,来完成一个连续动作。防止事件接受不到actionup。

在viewgroup的dispatchtouchevent的时候首先会调用onInterceptTouchEvent这个方法主要是拦截事件的,也就是说这里要是拦截了就不会再向布局里面传递事件了,设置完拦截之后,会便利viewgroup所有的子孩子,然后比对这个事件的x,y点,然后比对是否属于子类view,如果属于就设置一个target为那个view,如果target是空的,这时候就有两种情况:一种是点击事件发生在本viewgroup上,这时候就要调用viewgroup的的ontouchevent方法了。另一种情况就是我们说的触发了cancel。实际cancel就是给我们一个状态的标识符,没有什么处理意义。

传递给子类的dispatchtouchevent之后,就是一个迭代过程,其中viewgroup要不断的传递,直到遇到view。

view处理的时候,也是首先调用dispatchtouchevent,这个过程有很多注意的:首先会看ontouchlistener有没有,有的话就会调用ontouch事件,假如没有或者是事件没有被消费,就传递到view的ontouchevent中,这时候会首先看一下你的clickable或者longclickable是否是可以执行的,因为view的话默认的事件就是这两个,后面的处理actiondown,actionup,actionmove就是处理如何识别这两个事件。actionmove里面主要是处理看move的幅度大不大,假如只是很小的范围移动,就认为是点击事件,否则不是。

要正确的识别点击和长按实际上是使用了消息,在viewconfiguration中定义了点击和长按的时间值。然后在actiondown的时候向消息队列发送了一个延时消息,假如在长按的时间内,执行了up,那么就从队列中去除这条消息,那么长按事件就不会执行,如果down时间超了,那么延时消息自动就执行了。所以长按和短按都是基于这个原理实现的。

总的来说,事件传递主要是由根布局使用dispatchtouchevent分发,然后假如viewgroup要处理,就要使用onInterceptTouchEvent来进行拦截,拦截之后交给ontouchevent处理,假如view要执行就要让ontouchevent返回true,然后在查看你是否设置监听和clickable。也就是说ontouch优先级最高,还要保证你的clickable是true,然后才会执行onclick事件。当然假如是自定义的ontouchevent,那就完全是你自己写事件处理了。

android view :事件的更多相关文章

  1. Android View 事件分发机制 源码解析 (上)

    一直想写事件分发机制的文章,不管咋样,也得自己研究下事件分发的源码,写出心得~ 首先我们先写个简单的例子来测试View的事件转发的流程~ 1.案例 为了更好的研究View的事件转发,我们自定以一个My ...

  2. android view事件分发机制

    首先我们先写个简单的例子来测试View的事件转发的流程~ 1.案例 为了更好的研究View的事件转发,我们自定以一个MyButton继承Button,然后把跟事件传播有关的方法进行复写,然后添加上日志 ...

  3. Android View事件机制一些事

    本文主要讲述: 自己对View事件机制的一些理解 在项目中遇到的一些坑,解决方案 收集了一些View的事件机制问题 事件的分发原理图 对于一个root viewgroup来说,如果接受了一个点击事件, ...

  4. Android View事件分发-从源码分析

    View事件分发-从源码分析 学习自 <Android开发艺术探索> https://blog.csdn.net/qian520ao/article/details/78555397?lo ...

  5. 谈谈我对Android View事件分发的理解

    写这篇博客的缘由.近期因为项目中用到相似一个LinearLayout中水平布局中,有一个TextView和Button,然后对该LinearLayout布局设置点击事件.点击TextView能够触发该 ...

  6. Android View事件分发与传递

    在Android中,人们主要通过手指与系统交互.Android把所有的touch事件都被封装成MotionEvent来进行处理,其中包括了手指点击的位置,时间等信息.其事件类型主要包括:ACTION_ ...

  7. Android View 事件分发机制 源代码解析 (上)

    一直想写事件分发机制的文章,无论咋样,也得自己研究下事件分发的源代码.写出心得~ 首先我们先写个简单的样例来測试View的事件转发的流程~ 1.案例 为了更好的研究View的事件转发,我们自定以一个M ...

  8. android View事件分发机制结论

    原始博客有对源码的分析:http://blog.csdn.net/lmj623565791/article/details/39102591 结论:1.view事件的分发流程: dispatchTou ...

  9. Android View事件传递机制

    ViewGroup dispatchTouchEvent onInterceptTouchEvent onTouch View dispatchTouchEvent onTouch 假设View的层级 ...

  10. Android View事件机制 21问21答

    原文: http://www.cnblogs.com/punkisnotdead/p/5179115.html#3358859 1.View的坐标参数 主要有哪些?分别有什么注意的要点? 答:Left ...

随机推荐

  1. CentOS_7.2编译安装PHP_5.6.20添加扩展模块

    添加ZendGuardLoader扩展: # 解压ZendGuardLoader.so到"/usr/local/php/lib/php/extensions/no-debug-non-zts ...

  2. 获取checkbox后面的文本内容

    http://alygle.blog.51cto.com/1922399/669040 <head> <meta http-equiv="Content-Type" ...

  3. MySql学习(三) —— 子查询(where、from、exists) 及 连接查询(left join、right join、inner join、union join)

    注:该MySql系列博客仅为个人学习笔记. 同样的,使用goods表来练习子查询,表结构如下: 所有数据(cat_id与category.cat_id关联): 类别表: mingoods(连接查询时作 ...

  4. 新手mysql 基础语法

    SELECT * from new; SELECT stuname FROM new; //查询某一列 SELECT DISTINCT stuname FROM new; //查询同一列中不同的值 S ...

  5. Bootstrap <基础二十三>页面标题(Page Header)

    页面标题(Page Header)是个不错的功能,它会在网页标题四周添加适当的间距.当一个网页中有多个标题且每个标题之间需要添加一定的间距时,页面标题这个功能就显得特别有用.如需使用页面标题(Page ...

  6. Bootstrap<基础六> 表单

    Bootstrap 通过一些简单的 HTML 标签和扩展的类即可创建出不同样式的表单. 表单布局 Bootstrap 提供了下列类型的表单布局: 垂直表单(默认) 内联表单 水平表单 垂直或基本表单 ...

  7. http get/post解决乱码问题

    <form method="默认为get"-> <s:form mothod="默认为post"-> ================= ...

  8. 第十篇.bootstrap轮播

    使用bootstrap的轮播插件可以向站点添加滑块,内容可以是图像,内嵌框架,视频或其它任何内容,使用轮播插件需要引入bootstrap.min.js. <div id="carous ...

  9. 006 复杂的数据类型&函数(方法)

    2016-01-16 1.变量类型int double string char bool decimal变量的使用规则:先声明再赋值最后使用int number;number=10; number=2 ...

  10. python中if __name__ == '__main__': 的解析

    当你打开一个.py文件时,经常会在代码的最下面看到if __name__ ==  '__main__':,现在就来介 绍一下它的作用. 模块是对象,并且所有的模块都有一个内置属性 __name__.一 ...