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。
过程中看到有篇文章里对dispatchTouchEvent的代码进行了凝视,能够更清楚的说明问题。详细例如以下。引用地址为:http://blog.csdn.net/hdxiaoyu2/article/details/25563453
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (mInputEventConsistencyVerifier != null) {
mInputEventConsistencyVerifier.onTouchEvent(ev, 1);
} // Check for interception.
final boolean intercepted;//拦截的标记变量
if (actionMasked == MotionEvent.ACTION_DOWN
|| mFirstTouchTarget != null) {
final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
if (!disallowIntercept) { //调用自身的 onInterceptTochEvent。推断是否须要拦截
intercepted = onInterceptTochEvent(ev);
ev.setAction(action); // restore action in case it was changed
} else {
intercepted = false;
}
} else {
// There are no touch targets and this action is not an initial down
// so this view group continues to intercept touches.
intercepted = true;
} //假如没拦截
if (!canceled && !intercepted) {
if (actionMasked == MotionEvent.ACTION_DOWN
|| (split && actionMasked == MotionEvent.ACTION_POINTER_DOWN)
|| actionMasked == MotionEvent.ACTION_HOVER_MOVE) { if (newTouchTarget == null && childrenCount != 0) {
final float x = ev.getX(actionIndex);
final float y = ev.getY(actionIndex);
// Find a child that can receive the event.
// Scan children from front to back.
final View[] children = mChildren; final boolean customOrder = isChildrenDrawingOrderEnabled();
//遍历全部的子View,而且调用他们的事件分发方法dispatchTouchEvent() for (int i = childrenCount - 1; i >= 0; i--) { final int childIndex = customOrder ? getChildDrawingOrder(childrenCount, i) : i;
final View child = children[childIndex];
if (!canViewReceivePointerEvents(child)
|| !isTransformedTouchPointInView(x, y, child, null)) {
continue;
} newTouchTarget = getTouchTarget(child);
//newTouchTarget表示事件传递的View目标。当不为空的时候,直接跳出循环
if (newTouchTarget != null) { newTouchTarget.pointerIdBits |= idBitsToAssign;
break;
} resetCancelNextUpFlag(child);
//递归调用子View分发事件方法,
if (dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)) { mLastTouchDownTime = ev.getDownTime();
mLastTouchDownIndex = childIndex;
mLastTouchDownX = ev.getX();
mLastTouchDownY = ev.getY();
//设置分发目标newTouchTarget为当前View
newTouchTarget = addTouchTarget(child, idBitsToAssign);
//标记子View的分发结果,为True的话。以下的代码是不会调用当前View的onTouch方法的,也就是规则1生成的原因
alreadyDispatchedToNewTouchTarget = true;
break;
}
}
} }
} if (mFirstTouchTarget == null) {
// No touch targets so treat this as an ordinary view.
handled = dispatchTransformedTouchEvent(ev, canceled, null,
TouchTarget.ALL_POINTER_IDS);
} else {
// Dispatch to touch targets, excluding the new touch target if we already
// dispatched to it. Cancel touch targets if necessary.
TouchTarget predecessor = null;
TouchTarget target = mFirstTouchTarget;
while (target != null) {
final TouchTarget next = target.next; //假设刚才alreadyDispatchedToNewTouchTarget设为True的话。就不运行以下的dispatchTransformedTouchEvent
//alreadyDispatchedToNewTouchTarget是由子View的onTouch返回值决定的, if (alreadyDispatchedToNewTouchTarget && target == newTouchTarget) {
handled = true;
} else {
final boolean cancelChild = resetCancelNextUpFlag(target.child)
|| intercepted; //运行自身的Touch事件,
if (dispatchTransformedTouchEvent(ev, cancelChild,
target.child, target.pointerIdBits)) {
handled = true;
}
if (cancelChild) {
if (predecessor == null) {
mFirstTouchTarget = next;
} else {
predecessor.next = next;
}
target.recycle();
target = next;
continue;
}
}
predecessor = target;
target = next;
}
}
}
另外还看到两篇将的不错的。能够作为參考:
http://www.infoq.com/cn/articles/android-event-delivery-mechanism
http://blog.csdn.net/hdxiaoyu2/article/details/25563453
http://yizhi401.blog.51cto.com/6500239/1364958
版权声明:本文博主原创文章,博客,未经同意不得转载。
Android MotionEvent事故响应机制的更多相关文章
- Android MotionEvent事件响应机制
在android中,事件主要包括点击.长按.拖曳.滑动等操作,这些构成了Android的事件响应,总体来说,所有的事件都由如下三个部分作为基础构成: 按下(action_down),移动(action ...
- Android之事件分发机制
本文主要包括以下内容 view的事件分发 viewGroup的事件分发 首先来看两张图 在执行touch事件时 首先执行dispatchTouchEvent方法,执行事件分发. 再执行onInterc ...
- Android View 事件分发机制详解
想必很多android开发者都遇到过手势冲突的情况,我们一般都是通过内部拦截和外部拦截法解决此类问题.要想搞明白原理就必须了解View的分发机制.在此之前我们先来了解一下以下三个非常重要的方法: di ...
- Android平台的事件处理机制和手指滑动例子
Android平台的事件处理机制有两种 基于回调机制的事件处理:Android平台中,每个View都有自己的处理事件的回调方法,开发人员可以通过重写View中的这些回调方法来实现需要的响应事件. 基于 ...
- Android 的事件传递机制,详解
Android 的事件传递机制,详解 前两天和一个朋友聊天的时候.然后说到事件传递机制.然后让我说的时候,忽然发现说的不是非常清楚,事实上Android 的事件传递机制也是知道一些,可是感觉自己知道的 ...
- Android触摸事件传递机制
简单梳理一下Android触摸事件传递机制的知识点. 一.View与ViewGroup的关系 View和ViewGroup二者的继承关系如下图所示: View是Android中最基本的一种UI组件,它 ...
- 使用Android SwipeRefreshLayout了解Android的嵌套滑动机制
SwipeRefreshLayout 是在Android Support Library, revision 19.1.0加入到support v4库中的一个下拉刷新控件,关于android的下拉刷新 ...
- Android Touch事件传递机制 二:单纯的(伪生命周期)
转载于:http://blog.csdn.net/yuanzeyao/article/details/38025165 在前一篇文章中,我主要讲解了Android源码中的Touch事件的传递过程,现在 ...
- Android Touch事件传递机制 一: OnTouch,OnItemClick(监听器),dispatchTouchEvent(伪生命周期)
ViewGroup View Activity dispatchTouchEvent 有 有 有 onInterceptTouchEvent 有 无 无 onTouchEvent 有 有 有 例 ...
随机推荐
- 提高PHP编程效率的方法
用单引号代替双引号来包含字符串,这样做会更快一些.因为PHP会在双引号包围的字符串中搜寻变量,单引号则不会,注意:只有echo能这么做,它是一种可以把多个字符串当作参数的“函数”(译注:PHP手册中说 ...
- C# webservice初探
转载请注明出处Coder的不平庸:http://blog.csdn.net/pearyangyang/article/details/46348633 因为工作的终端曾经是直接对数据库进行操作,导致每 ...
- poj2942 Knights of the Round Table,无向图点双联通,二分图判定
点击打开链接 无向图点双联通.二分图判定 <span style="font-size:18px;">#include <cstdio> #include ...
- meta标签详解:源http://blog.csdn.net/kongjiea/article/details/17092413
一.大众机型常用meta标签name的设置 1.name之viewport <meta name="viewport" content=""> 说明 ...
- Vs2012在Linux应用程序开发(3):加入新平台hi3516
下面我们将VS2012添加一个新的平台支持,由于近来与哈斯hi3516.就选它吧! 1.1 复制平台文件 原来一直认为要让VS支持一个新的平台须要编写代码,某天在看MSBUILD文件夹的时候突 ...
- [PATCH] UBUNTU: SAUCE: (no-up) apparmor: Sync to apparmor3 - RC1(v3.4.x kernel)
ubuntu touch v3.4 kernel AppArmor v3 backport patch 地址1:https://github.com/multirom-aries/ubuntu-pho ...
- 如何使用 yum 安装/更新/移除 软件
如何使用 yum 安装/更新/移除 软件 一. 建立仓库(repository)和源 a) 拷贝所以相关rpm包到某个目录 b) 执行createrepo /目录/目录/目录/目录 注意:b)中 ...
- template method pattern
//DataViewer.cs using System; namespace TemplateMethodSample { abstract class DataViewer { //抽象方法:获取 ...
- 【原创】leetCodeOj --- Merge k Sorted Lists 解题报告
题目地址: https://oj.leetcode.com/problems/merge-k-sorted-lists/ 题目内容: /** * Definition for singly-linke ...
- HDU 4311 Meeting point-1 && HDU 4312 Meeting point-2
这俩个题 题意::给出N(<1e5)个点求找到一个点作为聚会的地方,使每个点到达这里的距离最小.4311是 曼哈顿距离 4312是 切比雪夫距离: 曼哈顿距离 :大家都知道 对于二维坐标系a( ...