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 有 有 有 例 ...
随机推荐
- 我写了一起 Makefile(一)
我写了一起 Makefile 陈皓 概述—— 什么是makefile?也许非常多Winodws的程序猿都不知道这个东西,由于那些Windows的IDE都为你做了这个工作.但我认为要作一个好的和pro ...
- App如何选择移动广告平台的开发者3 - 选择标准广告平台
App开发公司.通常他们不能走品牌.要挑品牌的能力,我们将面临两大问题:业务团队.广告填充率.一系列的问题,以现金周期. 无线商务本才刚刚开始,大多数都是没有商业经验.产品.设计.运营.销售的人才都不 ...
- Xamarin 安装步骤
原文:Xamarin 安装步骤 1.下载并解压吾乐吧软件站提供的“Mono for Android 离线包” 安装:jdk-6u45-windows-i586.exe (就算你是64位系统,也要安装i ...
- 【ECSHOP插件】商品颜色尺寸仿淘宝选择功能免费发布
先放效果图,如此实用的功能是不是迫不及待的要添加到自己的网店中了呢 牵涉到的修改文件(default模板为例) /themes/default/style.css /themes/default/ ...
- 讨论JDK的File.equal()
我们一般比较两个文件中的对象是相同的文件,通常使用java.io.File.equal().这里,equal()是不是文件内容的比较结果为.象是否指向同一个文件. File的equal()方法.实际上 ...
- Javascript 优化
Javascript 优化 作者:@gzdaijie本文为作者原创,转载请注明出处:http://www.cnblogs.com/gzdaijie/p/5324489.html 目录 1.全局变量污染 ...
- java.lang.RuntimeException: Method called after release()
主要引起是因為在 camera.stopPreview(); camera.release(); 前沒有將setPreviewCallback 設置為null, 解決情況: public void ...
- 【原创】leetCodeOj --- Sliding Window Maximum 解题报告
天,这题我已经没有底气高呼“水”了... 题目的地址: https://leetcode.com/problems/sliding-window-maximum/ 题目内容: Given an arr ...
- Oracle SQL Lesson (8) - 使用集合操作符(Union,Intersect,Minus)
集合操作符UNION/UNION ALLINTERSECTMINUS Union All不排序,不去重,其余均升序且去重.create table e1 as select * from emp wh ...
- 1pdf
Document doc = new Document(new iTextSharp.text.Rectangle(564, 351)); PdfWriter writer= PdfWriter.G ...