Android MotionEvent事件响应机制
在android中,事件主要包括点击、长按、拖曳、滑动等操作,这些构成了Android的事件响应,总体来说,所有的事件都由如下三个部分作为基础构成:
按下(action_down),移动(action_move),抬起(action_up)。各种响应归根结底都是基于View以及ViewGroup的,这两者中响应的方法分别有:
View.java中:
publi boolean dispatchTouchEvent(MotionEvent event)
public boolean onTouchEvent(MotionEvent event)
ViewGroup.java中
public boolean dispatchTouchEvent(MotionEvent event)
public boolean onTouchEvent(MotionEvent event)
public boolean onInterceptTouchEvent(MotionEvent event)
在组件嵌套的情况下,对于事件的响应处理会从最顶层的组件不断向子组件传递,一直到最后的View组件。
可以看到ViewGroup中比View中多出了一个onInterceptTouchEvent方法,这是因为ViewGroup组件可以存在子组件,因此需要通过Intercept判断是否
将该事件传递到子组件中。
函数的具体功能如下:
onTouchEvent是真正用来进行业务逻辑处理的地方,返回true表示已经将该事件消费,返回false表明事件继续传递。
onInterceptTouchEvent是用来进行判断是否需要对事件进行拦截从而阻止其继续往子组件传递的,返回false表示无需拦截,则递归的调用子组件的dispatchTouchEvent
方法;返回true表示需要拦截,则直接调用本组件的onTouchEvent方法进行处理。
以上两个的功能相对好理解一些,最主要的是第三个,之前在网上看了很多,但是都没有讲的特别清楚的。大都说是用于事件分发的,返回true表示不继续分发,返回false表
示继续分发。但是一直没讲明白这个跟采用onInterceptTouchEvent的区别在哪里。。
直接点说,Android对于touch事件的处理是通过递归来进行的,而这种递归就体现在dispatchTouchEvent上。以上所写的两个函数就是在dispatchTouchEvent中被调用并
且执行从而实现其分发的业务逻辑的。
在dispatchTouchEvent中有可能会调用三个方法:
1、本组件的onInterceptTouchEvent
2、子组件的dispatchTouchEvent
3、本组件的onTouchEvent
ViewGroup中dispatchTouchEvent()具体的执行逻辑:
1、首先执行本组件的onInterceptTouchEvent。如果返回false,表明无需拦截,则调用第二个方法,即子组件的dispatchTouchEvent方法;如果返回true,无需向子组件
传递,则直接调用本组件的onTouchEvent方法
2、第一步中如果需要向子组件传递事件。如果递归调用子组件的dispatchTouchEvent返回false,则调用本组件的onTouchEvent方法;如果返回true,则无需调用本组件的
onTouchEvent方法
3、根据前两步的执行结果,将该dispatchTouchEvent的返回值返回给父组件的dispatchTouchEvent方法。
view中的dispatchTouchEvent会直接调用其自身的onTouchEvent。
一般没有必要重写dispatchTouchEvent方法,如果一定要重写,请注意调用super.dispatchTouchEvent()方法,否则递归调用到此处即停止。
在不考虑dispatchTouchEvent的情况下,简单的执行流程是这样的:
最顶层的组件首先响应事件,然后不断向子组件进行传递,调用子组件的onInterceptTouchEvent方法,一直到某个组件A的onInterceptTouchEvent
方法返回true或者到达了view组件,然后调用该组件的onTouchEvent方法,之后不断向父组件进行返回,调用父组件的onTouchEvent直到某个父组件
的onTouchEvent方法返回true。
其实就是个首先从父组件不断向下调用onInterceptTouchEvent,然后从子组件不断向上调用onTouchEvent的过程。
还需要注意的:
1、假如这个过程中某个组件截获并处理了ACTION_DOWN事件,则之后相应的ACTION_MOVE、ACTION_UP等其他事件将不再会被传递到他的子孙组
件,而是传递到该组件后就执行返回的流程。
2、如果某个组件的onInterceptTouchEvent对ACTION_DOWN返回true,则之后的ACTION_MOVE,ACTION_DOWN等将不会再执行本onInterceptTouchEvent,
而是直接传递给本组件的onTouchEvent,但是依然会经过其父组件的onInterceptTouchEvent。
MotionEvent事件对象
一般我们是在View的onTouchEvent方法中处理MotionEvent对象的.
public boolean onTouchEvent(MotionEvent event)
在这里我们需要从一个MotionEvent对象中获得哪些信息呢?
(1)首先应该是事件的类型吧?
可以通过getAction(),在android2.2之后加入多点触控支持之后使用getActionMasked()方法.
这两个方法的区别见后文.
主要的事件类型有:
ACTION_DOWN: 表示用户开始触摸.
ACTION_MOVE: 表示用户在移动(手指或者其他)
ACTION_UP:表示用户抬起了手指
ACTION_CANCEL:表示手势被取消了,一些关于这个事件类型的讨论见:http://stackoverflow.com/questions/11960861/what-causes-a-motionevent-action-cancel-in-android
还有一个不常见的:
ACTION_OUTSIDE: 表示用户触碰超出了正常的UI边界.
但是对于多点触控的支持,Android加入了以下一些事件类型.来处理,如另外有手指按下了,
有的手指抬起来了.等等:
ACTION_POINTER_DOWN:有一个非主要的手指按下了.
ACTION_POINTER_UP:一个非主要的手指抬起来了
(2)事件发生的位置,x,y轴
getX() 获得事件发生时,触摸的中间区域在屏幕的X轴.
getY() 获得事件发生时,触摸的中间区域在屏幕的X轴.
在多点触控中还可以通过:
getX(int pointerIndex) ,来获得对应手指事件的发生位置. 获得Y轴用getY(int pointerIndex)
(3)其他属性
getEdgeFlags():当事件类型是ActionDown时可以通过此方法获得,手指触控开始的边界. 如果是的话,有如下几种值:EDGE_LEFT,EDGE_TOP,EDGE_RIGHT,EDGE_BOTTOM
转载:
http://www.2cto.com/kf/201406/308037.html
https://my.oschina.net/banxi/blog/56421
Android MotionEvent事件响应机制的更多相关文章
- Android MotionEvent事故响应机制
于android于.主要活动包括点击.按.拖累.滑动等操作,这些构成了Android事件响应,总体而言,,所有事件由例如以下三部分构成的基础: 按(action_down),搬家(action_mov ...
- Android之事件分发机制
本文主要包括以下内容 view的事件分发 viewGroup的事件分发 首先来看两张图 在执行touch事件时 首先执行dispatchTouchEvent方法,执行事件分发. 再执行onInterc ...
- Android 的事件传递机制,详解
Android 的事件传递机制,详解 前两天和一个朋友聊天的时候.然后说到事件传递机制.然后让我说的时候,忽然发现说的不是非常清楚,事实上Android 的事件传递机制也是知道一些,可是感觉自己知道的 ...
- Android触摸事件传递机制
简单梳理一下Android触摸事件传递机制的知识点. 一.View与ViewGroup的关系 View和ViewGroup二者的继承关系如下图所示: View是Android中最基本的一种UI组件,它 ...
- Android Touch事件传递机制 二:单纯的(伪生命周期)
转载于:http://blog.csdn.net/yuanzeyao/article/details/38025165 在前一篇文章中,我主要讲解了Android源码中的Touch事件的传递过程,现在 ...
- Android Touch事件传递机制 一: OnTouch,OnItemClick(监听器),dispatchTouchEvent(伪生命周期)
ViewGroup View Activity dispatchTouchEvent 有 有 有 onInterceptTouchEvent 有 无 无 onTouchEvent 有 有 有 例 ...
- Android View 事件分发机制 源码解析 (上)
一直想写事件分发机制的文章,不管咋样,也得自己研究下事件分发的源码,写出心得~ 首先我们先写个简单的例子来测试View的事件转发的流程~ 1.案例 为了更好的研究View的事件转发,我们自定以一个My ...
- Android touch 事件传递机制
前言: (1)在自定义view的时候经常会遇到事件拦截处理,比如在侧滑菜单的时候,我们希望在侧滑菜单里面有listview控件,但是我们希望既能左右滑动又能上下滑动,这个时候就需要对触摸的touch事 ...
- 【转】Android TouchEvent事件传递机制
Android TouchEvent事件传递机制 事件机制参考地址: http://www.cnblogs.com/sunzn/archive/2013/05/10/3064129.html ht ...
随机推荐
- linux中mysql基本操作
1.linux下启动mysql的命令: mysqladmin start /ect/init.d/mysql start (前面为mysql的安装路径) 2.linux下重启mysql的命令: mys ...
- Oracle数据库名、实例名、数据库域名、数据库服务名、全局数据库名的辨析
我也是看着各位大婶的博客然后一点点的来学习,不求全会,留个印象 数据库名 数据库名就是一个数据库的标识,用参数DB_NAME表示. 如果一台机器上安装了多个数据库,那么每一个数据库都有一个数据库名. ...
- Object-c:两种文件读写的对比
一.读写方法对比:(主要针对本地读取本地文件) 方式\操作 读 写 非URL方式 stringWithContentsOfFile writeToFile URL方式 stringWithConten ...
- bzoj 2957: 楼房重建 线段树
2957: 楼房重建 Time Limit: 10 Sec Memory Limit: 256 MB[Submit][Status][Discuss] Description 小A的楼房外有一大片施 ...
- 关于seafile启动的问题解决
过了一个国庆,同事反映说seafile服务挂掉了,无法正常连接. 刚才解决了一下,把相关问题简要记录一下: 1.首先连接阿里云,获得相关IP地址(如果已知IP地址,则不需要该步骤)
- LotteryDrawing
import java.util.*; public class MyTest{ public static void main(String[] args){ Scanner in = new Sc ...
- FileCopy
/*[入]指的是到内存里,[出]指的是到内存外*/ import java.io.*; public class MyReadFile{ public static void main(String[ ...
- shiro-web整合
1.所需要jar <!-- shiro核心包 --> <dependency> <groupId>org.apache.shiro</groupId> ...
- [转载] tmux的使用tips
原文: http://tangosource.com/blog/a-tmux-crash-course-tips-and-tweaks/
- linux终端下 编译c语言程序
linux终端下,编译C语言程序步骤为: 采用vi进行源代码编写,编写完成后,:wq存盘退出,如: vi test.c 在命令行下,运行gcc编译程序,生成执行码,如: gcc -o test te ...