大家好,我是你们的康志哥。

Android 事件传递机制是个很复杂的过程,大家读完Android事件分发机制完全解析(终极版)后,假如还有疑问,欢迎继续阅读这篇更加详细的分析文章,此篇文章还会介绍Android事件分发机制中对事件序列的处理。

-----------------------------------------------------------------------------------------------------------------------------------------------------------

首先要知道我们对于屏幕的所有操作,包括点击、放开、滑动,以及由这些基本操作组成的放大、缩小、旋转等操作全部是被封装在MotionEvent对象中进行操作的。我们需要通过getAction()判断是何种事件。这些事件包括如下6种:

ACTION_DOWN: 第一个点按下时触发

ACTION_UP: 屏幕上唯一的一个点抬起时触发

ACTION_MOVE: 当屏幕上的点移动时触发。

ACTION_POINTER_DOWN: 当屏幕上已经有一点按住,再按下其他点便会触发该事件。

ACTION_POINTER_UP: 当屏幕上有多个点被按住,松开其中的点时触发(非最后一个点,最后一个点触发ACTION_UP)。

ACTION_CANCEL:当前的手势被释放时会触发,当前手势指的是从ACTION_DOWN开始以及后面一系列的ACTION_MOVE、ACTION_POINTER_DOWN、ACTION_POINTER_UP操作。

其中, 事件序列的概念:

同一个事件序列是指从手指接触屏幕的那一刻起,到手指离开屏幕的那一刻结束,在这个过程中所产生的一系列事件,这个事件序列以down事件开始,中间含有数量不定的move事件,最终以up事件结束。

事件序列并不是一个list,它们是独立的MotionEvent,一个一个地出现和被处理。

到这里我们就可以写出屏幕触摸事件相应的代码了:

[java]  view plain  copy
  1. @Override  
  2.     public boolean onTouchEvent(MotionEvent ev) {  
  3.   
  4.         switch (ev.getAction()) {  
  5.         case MotionEvent.ACTION_DOWN:  
  6.             // 第一个点按下去的相关处理  
  7.             break;  
  8.         case MotionEvent.ACTION_MOVE:  
  9.             // 手指在屏幕上移动相关处理  
  10.             break;  
  11.         case MotionEvent.ACTION_UP:  
  12.             // 屏幕上最后一个点离开屏幕时相关处理  
  13.             break;  
  14.         }  
  15.         return super.onTouchEvent(ev);  
  16.     }  

只要把握这六种事件就可以了,是不是很简单呢?但是Touch事件并非这么简单,到这里还有很多问题没有搞清楚。Touch事件的事件源,处理者是谁?处理的具体方法有哪些?具体的流程如何?下面还请听详细分解。

Touch事件传递

Touch事件的处理分为三个层面:Activity,ViewGroup,View。我们所说的Touch事件传递便是在这三个层面之间进行传递的。而事件的传递,依靠的是三个方法dispatchTouchEvent()­­­----事件分派,onInterceptTouchEvent()----事件拦截,onTouchEvent()----事件处理。我们上面看到的示例代码中onTouchEvent()便是我们实际处理操作的方法。而至于事件是如何传递的,上面我们并不清楚。下表给出这三个层次具体的实例类和和这三个方法之间的关系。

层次

实例类

方法

Activity

 

dispatchTouchEvent, onTouchEvent

ViewGroup

RelativeLayout, FrameLayout, LinearLayout, 

AbsoluteLayout, ListView,ScrollView...

dispatchTouchEvent, onInterceptTouchEvent, 

onTouchEvent

View

Button, EditText, TextView, ImageView

dispatchTouchEvent, onTouchEvent 

表一 三个层次及其具体实例类和三个方法之间的对应关系

下面将通过一个示例来表现Touch事件究竟是如何在这三个层面之间进行传递的。我们拿下面这张图来作为Touch事件传递的层次图。

Android事件分发机制完全解析(终极版二)_第1张图片

图一 Touch事件传递涉及层次图

所有的Touch事件一定都是从ACTION_DOWN这个事件开始的,那么当你按下屏幕那一刻开始,也就是触发了ACTION_DOWN这个事件。Touch事件传递便开始工作了。以上面这张图为例。

当ACTION_DOWN被触发,系统会调用Activity的dispatchTouchEvent方法,对该事件进行分发,然后将事件分发到RelativeLayout的dispatchTouchEvent方法进行处理。RelativeLayout会调用它的onInterceptTouchEvent方法判断是否要拦截下这个事件,然后自己处理。如果返回true那个执行RelativeLayout的onTouchEvent方法,如果返回false那么这条传递链就继续向下延伸到RelativeLayout的子View –TextView的dispatchTouchEvent,由于TextView已经不能够有子View了,不能够再向下传递,dispatchTouchEvent再将事件分发到TextView的onTouchEvent方法,onTouchEvent返回true或者false:

1)     如果onTouchEvent返回true,表示TextView能够处理该事件,那么事件就不再传递下去,后续的事件(ACTION_MOVE, ACTION_POINTER_DOWN, ACTION_POINTER_UP,ACTION_UP)都会按照同样的传递过程进行传递,最后交给TextView的onTouchEvent方法进行处理。

2)     如果onTouchEvent返回false,表示TextView不能够处理该事件,这时事件就会发生回传,传递给其父View– RelativeLayout的onTouchEvent方法,如果onTouchEvent方法返回true,表示RelativeLayout可以处理该事件,那么后续的事件传递到RelativeLayout的onInterceptTouchEvent方法的时候就会拦截下来直接由RelativeLayout的onTouchEvent进行处理;如果onTouchEvent方法返回false,那么事件继续进行上传到Activity的OnTouchEvent,如果返回true由它进行处理,如果返回false,由于它已经是最顶层了,事件传递到此为止,Touch事件无效。

说了这么多,不如来一幅生动形象的图来描述整个的Touch事件传递过程吧。

Android事件分发机制完全解析(终极版二)_第2张图片

上面两幅图分别表现的是1)和2)的事件传递图,实线表示ACTION_DOWN事件的传递,虚线表示后续其它事件的传递。第一张图中TextView的onTouchEvent处理该事件,那么第二次仍然按照原路传递到TextView由它进行处理;第二张图中TextView的onTouchEvent不能处理该事件,那么就回传到RelativeLayout的onTouchEvent进行处理,可以处理便不进行回传,后续其它事件再传递,传递到RelativeLayout就由它来进行处理,不需要再向下传递。

到这里Touch事件传递机制的说明就算完成了。但Touch事件仍有很多让人疑惑不解的, 比如ACTION_MOVE拖动的方向距离是如何实现的, ACTION_POINTER_UP, ACTION_POINTER_DOWN有是如何实现的。下面在对它们进行简要的讲解。

ACTION_MOVE拖动方向距离是通过MotionEvent的getX() getY(), getRawX()getRawY 这四个方法得到的。这里值得一提的是前面两个方法是得到的是相对于当前Widget左上角的X, Y坐标,而后面两个方法得到的是以手机屏幕左上角为原点的X, Y      坐标。既然得到了当前坐标那么拖动的距离方向就很好计算了,通过当前ACTION_MOVE事件得到的X,Y坐标减去上一个事件(可能是ACTION_DOWN也可能是ACTION_MOVE)得到的X, Y坐标就可以得知拖动的方向距离了。

而ACTION_POINTER_UP,ACTION_POINTER_DOWN的实现则是通过方法getX(pointerIndex)实现的,pointerIndex表示的就是屏幕上面的点,这样我们就可以知道屏幕上的每个点的当前坐标了。

更多相关文章

  1. Android事件分发机制和一些疑问
  2. Android查询:模拟键盘鼠标事件(adb shell 实现)
  3. Android Webview适配屏幕宽度
  4. Android VideoView设置静音,Android 设置VideoView静音,Android
  5. Android Touch 事件的分发和消费机制
  6. ListView去掉分割线的几种方法
  7. SDK Platform Tools component is missing! Please use the SDK
  8. android中炫酷划屏事件及sqlite全部操作Demo(1)
  9. Android点击事件的四种写法

随机推荐

  1. android TextView 更换字体
  2. Android开发学习之布局
  3. Cocos2d-x 发布 Android
  4. Android仿Iphone屏幕底部弹出半透明Popup
  5. Android第三方开源对话消息提示框:SweetAl
  6. Android实现版本更新和自动安装
  7. 如何判断是手机端还是PC端?
  8. Activity实现自定义Dialog
  9. android集成sharesdk遇到的坑无法返回app
  10. android入门篇之ContentProvider学习笔记