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 有 有 有 例 ...
随机推荐
- BZOJ 1038 ZJOI2008 瞭望塔 半平面交
题目大意及模拟退火题解:见 http://blog.csdn.net/popoqqq/article/details/39340759 这次用半平面交写了一遍--求出半平面交之后.枚举原图和半平面交的 ...
- QT Programming 1
1.控制台输出 helloworld #include<QtCore/QCoreApplication> #include<QDebug> int main(int argc, ...
- zoj3822 期望dp
每天在一个n*m的棋盘上放棋子,问使得每一行,每一列都有棋子的期望天数 dp[n][m][k] 表示用k个棋子占据了n行,m列,距离目标状态还需要的期望天数 那么dp[n][m][k] = p1 * ...
- Makefile 管理工具 — Automake and Autoconf
该project下载路径:http://files.cnblogs.com/iTsihang/hello-2.0.zip automake 參考资料:http://www.linuxforum.net ...
- SQL Server :理解IAM 页
原文:SQL Server :理解IAM 页 在以前的文章里,我们讨论了数据页,GAM和SGAM,还有PFS页.今天我们一起来讨论下索引分配映射(Index Allocation Map:IAM)页. ...
- uptime
linux uptime命令主要用于获取主机运行时间和查询linux系统负载等信息.uptime命令过去只显示系统运行多久.现在,可以显示系统已经运行了多长时间,信息显示依次为:现在时间.系统已经运行 ...
- URAL 1728. Curse on Team.GOV(STL set)
题目链接:space=1&num=1728" target="_blank">http://acm.timus.ru/problem.aspx?space= ...
- cocos2d-x V3.0 呼叫加速度计 Acceleration
今天克服了一个问题,我觉得非常酷 哈哈. 今天得到解决cocos2d-x 3.0 呼叫重力加速器问题,上网查了很多资料 发现是不够,不解决这个问题,我不知道如果我使用3.0 这一问题的版本号,但是,这 ...
- mongodb笔记2
成功启动MongoDB后,再打开一个命令行窗口输入mongo,就可以进行数据库的一些操作. 输入help可以看到基本操作命令: show dbs:显示数据库列表 show collections:显示 ...
- JDK源码学习系列02----AbstractStringBuilder
JDK源码学习系列02----AbstractStringBuilder 因为看StringBuffer 和 StringBuilder 的源码时发现两者都继承了AbstractStringBuil ...