Android中有各种各样的事件,以响应用户的操作。这些事件可以分为按键事件和触屏事件。而Touch事件是触屏事件的基础事件,在进行Android开发时经常会用到,所以非常有必要深入理解它的原理机制。

Android Touch事件原理描述

一个最简单的屏幕触摸动作触发了一系列Touch事件:ACTION_DOWN->ACTION_MOVE->ACTION_MOVE->ACTION_MOVE...->ACTION_MOVE->ACTION_UP。

当屏幕中包含一个ViewGroup,而这个ViewGroup又包含一个子view,这个时候android系统如何处理Touch事件呢?到底是ViewGroup来处理Touch事件,还是子view来处理Touch事件呢?我只能很肯定的对你说不一定。呵呵,为什么呢?看看下面我的调查结果你就明白了。

Android系统中的每个View的子类都具有下面三个和TouchEvent处理密切相关的方法:

1)public boolean dispatchTouchEvent(MotionEvent ev)  这个方法用来分发TouchEvent

2)public boolean onInterceptTouchEvent(MotionEvent ev) 这个方法用来拦截TouchEvent

3)public boolean onTouchEvent(MotionEvent ev) 这个方法用来处理TouchEvent

当TouchEvent发生时,首先Activity将TouchEvent传递给最顶层的View, TouchEvent最先到达最顶层 view 的 dispatchTouchEvent ,然后由  dispatchTouchEvent 方法进行分发,如果dispatchTouchEvent返回true ,则交给这个view的onTouchEvent处理,如果dispatchTouchEvent返回 false ,则交给这个 view 的 interceptTouchEvent 方法来决定是否要拦截这个事件,如果 interceptTouchEvent 返回 true ,也就是拦截掉了,则交给它的 onTouchEvent 来处理,如果 interceptTouchEvent 返回 false ,那么就传递给子 view ,由子 view 的 dispatchTouchEvent 再来开始这个事件的分发。如果事件传递到某一层的子 view 的 onTouchEvent 上了,这个方法返回了 false ,那么这个事件会从这个 view 往上传递,都是 onTouchEvent 来接收。而如果传递到最上面的 onTouchEvent 也返回 false 的话,这个事件就会“消失”,而且接收不到下一次事件。

Android Touch事件实例分析

通过语言描述这个处理逻辑很抽象,下面我就用代码来具体说明一下。

layout配置文件 main.xml:

XML/HTML代码
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <test.lzqdiy.MyLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:orientation="vertical"
  4. android:layout_width="fill_parent"
  5. android:layout_height="fill_parent"
  6. android:gravity="center" >
  7. <test.lzqdiy.MyTextView
  8. android:layout_width="200px"
  9. android:layout_height="200px"
  10. android:id="@+id/tv"
  11. android:text="lzqdiy"
  12. android:textSize="40sp"
  13. android:textStyle="bold"
  14. android:background="#FFFFFF"
  15. android:textColor="#0000FF"/>
  16. </test.lzqdiy.MyLinearLayout>

节点层次很简单,一个LinearLayout中添加了一个TextView。

下面是java代码:

Java代码
  1. package test.lzqdiy;
  2. import android.app.Activity;
  3. import android.os.Bundle;
  4. public class TestTouchEventApp extends Activity {
  5. /** Called when the activity is first created. */
  6. @Override
  7. public void onCreate(Bundle savedInstanceState) {
  8. super.onCreate(savedInstanceState);
  9. setContentView(R.layout.main);
  10. }
  11. }
  12. package test.lzqdiy;
  13. import android.content.Context;
  14. import android.util.AttributeSet;
  15. import android.util.Log;
  16. import android.view.MotionEvent;
  17. import android.widget.LinearLayout;
  18. public class MyLinearLayout extends LinearLayout {
  19. private final String TAG = "MyLinearLayout";
  20. public MyLinearLayout(Context context, AttributeSet attrs) {
  21. super(context, attrs);
  22. Log.d(TAG, TAG);
  23. }
  24. @Override
  25. public boolean dispatchTouchEvent(MotionEvent ev) {
  26. int action = ev.getAction();
  27. switch (action) {
  28. case MotionEvent.ACTION_DOWN:
  29. Log.d(TAG, "dispatchTouchEvent action:ACTION_DOWN");
  30. break;
  31. case MotionEvent.ACTION_MOVE:
  32. Log.d(TAG, "dispatchTouchEvent action:ACTION_MOVE");
  33. break;
  34. case MotionEvent.ACTION_UP:
  35. Log.d(TAG, "dispatchTouchEvent action:ACTION_UP");
  36. break;
  37. case MotionEvent.ACTION_CANCEL:
  38. Log.d(TAG, "dispatchTouchEvent action:ACTION_CANCEL");
  39. break;
  40. }
  41. return super.dispatchTouchEvent(ev);
  42. }
  43. @Override
  44. public boolean onInterceptTouchEvent(MotionEvent ev) {
  45. int action = ev.getAction();
  46. switch (action) {
  47. case MotionEvent.ACTION_DOWN:
  48. Log.d(TAG, "onInterceptTouchEvent action:ACTION_DOWN");
  49. break;
  50. case MotionEvent.ACTION_MOVE:
  51. Log.d(TAG, "onInterceptTouchEvent action:ACTION_MOVE");
  52. break;
  53. case MotionEvent.ACTION_UP:
  54. Log.d(TAG, "onInterceptTouchEvent action:ACTION_UP");
  55. break;
  56. case MotionEvent.ACTION_CANCEL:
  57. Log.d(TAG, "onInterceptTouchEvent action:ACTION_CANCEL");
  58. break;
  59. }
  60. return false;
  61. }
  62. @Override
  63. public boolean onTouchEvent(MotionEvent ev) {
  64. int action = ev.getAction();
  65. switch (action) {
  66. case MotionEvent.ACTION_DOWN:
  67. Log.d(TAG, "---onTouchEvent action:ACTION_DOWN");
  68. break;
  69. case MotionEvent.ACTION_MOVE:
  70. Log.d(TAG, "---onTouchEvent action:ACTION_MOVE");
  71. break;
  72. case MotionEvent.ACTION_UP:
  73. Log.d(TAG, "---onTouchEvent action:ACTION_UP");
  74. break;
  75. case MotionEvent.ACTION_CANCEL:
  76. Log.d(TAG, "---onTouchEvent action:ACTION_CANCEL");
  77. break;
  78. }
  79. return true;
  80. }
  81. }
  82. package test.lzqdiy;
  83. import android.content.Context;
  84. import android.util.AttributeSet;
  85. import android.util.Log;
  86. import android.view.MotionEvent;
  87. import android.widget.TextView;
  88. public class MyTextView extends TextView {
  89. private final String TAG = "MyTextView";
  90. public MyTextView(Context context, AttributeSet attrs) {
  91. super(context, attrs);
  92. }
  93. @Override
  94. public boolean dispatchTouchEvent(MotionEvent ev) {
  95. int action = ev.getAction();
  96. switch (action) {
  97. case MotionEvent.ACTION_DOWN:
  98. Log.d(TAG, "dispatchTouchEvent action:ACTION_DOWN");
  99. break;
  100. case MotionEvent.ACTION_MOVE:
  101. Log.d(TAG, "dispatchTouchEvent action:ACTION_MOVE");
  102. break;
  103. case MotionEvent.ACTION_UP:
  104. Log.d(TAG, "dispatchTouchEvent action:ACTION_UP");
  105. break;
  106. case MotionEvent.ACTION_CANCEL:
  107. Log.d(TAG, "onTouchEvent action:ACTION_CANCEL");
  108. break;
  109. }
  110. return super.dispatchTouchEvent(ev);
  111. }
  112. @Override
  113. public boolean onTouchEvent(MotionEvent ev) {
  114. int action = ev.getAction();
  115. switch (action) {
  116. case MotionEvent.ACTION_DOWN:
  117. Log.d(TAG, "---onTouchEvent action:ACTION_DOWN");
  118. break;
  119. case MotionEvent.ACTION_MOVE:
  120. Log.d(TAG, "---onTouchEvent action:ACTION_MOVE");
  121. break;
  122. case MotionEvent.ACTION_UP:
  123. Log.d(TAG, "---onTouchEvent action:ACTION_UP");
  124. break;
  125. case MotionEvent.ACTION_CANCEL:
  126. Log.d(TAG, "---onTouchEvent action:ACTION_CANCEL");
  127. break;
  128. }
  129. return true;
  130. }
  131. }

为了指代方便,下面将MyLinearLayout简称为L,将MyTextView简称为T,L.onInterceptTouchEvent=true 表示的含义为MyLinearLayout中的onInterceptTouchEvent方法返回值为true,通过程序运行时输出的Log来说明调用时序。

第1种情况 L.onInterceptTouchEvent=false&& L.onTouchEvent=true &&T.onTouchEvent=true 输出下面的Log:

D/MyLinearLayout(11865): dispatchTouchEvent action:ACTION_DOWN
D/MyLinearLayout(11865): onInterceptTouchEvent action:ACTION_DOWN
D/MyTextView(11865): dispatchTouchEvent action:ACTION_DOWN
D/MyTextView(11865): ---onTouchEvent action:ACTION_DOWN
D/MyLinearLayout(11865): dispatchTouchEvent action:ACTION_MOVE
D/MyLinearLayout(11865): onInterceptTouchEvent action:ACTION_MOVE
D/MyTextView(11865): dispatchTouchEvent action:ACTION_MOVE
D/MyTextView(11865): ---onTouchEvent action:ACTION_MOVE
...........省略其他的ACTION_MOVE事件Log
D/MyLinearLayout(11865): dispatchTouchEvent action:ACTION_UP
D/MyLinearLayout(11865): onInterceptTouchEvent action:ACTION_UP
D/MyTextView(11865): dispatchTouchEvent action:ACTION_UP
D/MyTextView(11865): ---onTouchEvent action:ACTION_UP

结论:TouchEvent完全由TextView处理。

第2种情况  L.onInterceptTouchEvent=false&& L.onTouchEvent=true &&T.onTouchEvent=false 输出下面的Log:

D/MyLinearLayout(13101): dispatchTouchEvent action:ACTION_DOWN
D/MyLinearLayout(13101): onInterceptTouchEvent action:ACTION_DOWN
D/MyTextView(13101): dispatchTouchEvent action:ACTION_DOWN
D/MyTextView(13101): ---onTouchEvent action:ACTION_DOWN
D/MyLinearLayout(13101): ---onTouchEvent action:ACTION_DOWN
D/MyLinearLayout(13101): dispatchTouchEvent action:ACTION_MOVE
D/MyLinearLayout(13101): ---onTouchEvent action:ACTION_MOVE
...........省略其他的ACTION_MOVE事件Log
D/MyLinearLayout(13101): dispatchTouchEvent action:ACTION_UP
D/MyLinearLayout(13101): ---onTouchEvent action:ACTION_UP

结论:TextView只处理了ACTION_DOWN事件,LinearLayout处理了所有的TouchEvent。

第3种情况  L.onInterceptTouchEvent=true&& L.onTouchEvent=true 输出下面的Log:

D/MyLinearLayout(13334): dispatchTouchEvent action:ACTION_DOWN
D/MyLinearLayout(13334): onInterceptTouchEvent action:ACTION_DOWN
D/MyLinearLayout(13334): ---onTouchEvent action:ACTION_DOWN
D/MyLinearLayout(13334): dispatchTouchEvent action:ACTION_MOVE
D/MyLinearLayout(13334): ---onTouchEvent action:ACTION_MOVE
...........省略其他的ACTION_MOVE事件Log
D/MyLinearLayout(13334): dispatchTouchEvent action:ACTION_UP
D/MyLinearLayout(13334): ---onTouchEvent action:ACTION_UP

结论:LinearLayout处理了所有的TouchEvent。

第4种情况  L.onInterceptTouchEvent=true&& L.onTouchEvent=false 输出下面的Log:

D/MyLinearLayout(13452): dispatchTouchEvent action:ACTION_DOWN
D/MyLinearLayout(13452): onInterceptTouchEvent action:ACTION_DOWN
D/MyLinearLayout(13452): ---onTouchEvent action:ACTION_DOWN

结论:LinearLayout只处理了ACTION_DOWN事件,那么其他的TouchEvent被谁处理了呢?答案是LinearLayout最外层的Activity处理了TouchEvent。

Android Touch事件原理加实例分析的更多相关文章

  1. React-Native系列Android——Touch事件原理及状态效果

    Native原生相比于Hybrid或H5最大长处是具有流畅和复杂的交互效果,触摸事件便是当中重要一项,包括点击(Click).长按(LongClick).手势(gesture)等. 以最简单常见的点击 ...

  2. Android Touch事件传递机制 二:单纯的(伪生命周期)

    转载于:http://blog.csdn.net/yuanzeyao/article/details/38025165 在前一篇文章中,我主要讲解了Android源码中的Touch事件的传递过程,现在 ...

  3. Android touch事件的派发流程

    Android TouchEvent事件传递机制 通俗易懂,能够了解Touch事件派发的基本流程. Android中的dispatchTouchEvent().onInterceptTouchEven ...

  4. Android Touch事件传递机制 二:单纯的(伪生命周期) 这个清楚一点

    转载于:http://blog.csdn.net/yuanzeyao/article/details/38025165 在前一篇文章中,我主要讲解了Android源码中的Touch事件的传递过程,现在 ...

  5. Android Touch事件传递机制详解 下

    尊重原创:http://blog.csdn.net/yuanzeyao/article/details/38025165 资源下载:http://download.csdn.net/detail/yu ...

  6. Android Touch事件传递机制具体解释 下

    尊重原创:http://blog.csdn.net/yuanzeyao/article/details/38025165 资源下载:http://download.csdn.net/detail/yu ...

  7. Android Touch事件分发过程

    虽然网络上已经有非常多关于这个话题的优秀文章了,但还是写了这篇文章,主要还是为了加强自己的记忆吧,自己过一遍总比看别人的分析要深刻得多.那就走起吧. 简单演示样例 先看一个演示样例 : 布局文件 : ...

  8. Android Touch事件传递机制具体解释 上

    尊重原创:http://blog.csdn.net/yuanzeyao/article/details/37961997 近期总是遇到关于Android Touch事件的问题,如:滑动冲突的问题,曾经 ...

  9. Android Touch事件之二:dispatchTouchEvent()和onTouchEvent()篇

    2015-12-01 15:06:14 Android Touch事件第一篇:Touch事件在父ViewGroup和子View之间的传递简单分析了事件的传递流程,这次深入了解下dispatchTouc ...

随机推荐

  1. 结构体UT_LIST_ADD_LAST

    使用 UT_LIST_ADD_LAST(list, buf_pool->free, (&block->page)); /****************************** ...

  2. jquery 分页控件(二)

    上一章主要是关于分页控件的原理,代码也没有重构.在这一章会附上小插件的下载链接,插件主要就是重构逻辑部分,具体可以下载源文件看下,源代码也有注释.为了测试这个插件是能用的,我弄了个简单的asp.net ...

  3. SCOI2009windy数

    数位DP,还不怎么会…… 其中calc函数的计算分为三部分: 第一部分:统计最高位为0的情况,或者说不足最高位位数的数的个数 第二部分:统计最高位为1到a[len]-1的情况,直接调用数组即可 第三部 ...

  4. ubuntu下eclipse打开win下的代码中文出现乱码

    问题出现的原因:因为windows下默认的编码是GBK,在ubuntu下是UTF-8所以,所以在windows下的注释,在ubuntu下就变成了乱码. 解决的方案: 1)  eclipse->w ...

  5. Asp.Net 高性能框架 SqlSugar.ORM 2.3

    一.前言 SqlSugar从去年到现在已经一年了,版本从1.0升到了现在的2.3 ,这是一个稳定版本 ,有数家公司已经项目上线,在这里我将SqlSugar的功能重新整理成一篇新的贴子,希望大家喜欢. ...

  6. (Android Studio)添加按钮以及权重问题

    此文大部分摘自http://hukai.me/android-training-course-in-chinese/basics/firstapp/building-ui.html 注意到光标所在代码 ...

  7. [Bhatia.Matrix Analysis.Solutions to Exercises and Problems]ExI.5.10

    Every $k\times k$ positive matrix $A=(a_{ij})$ can be realised as a Gram matrix, i.e., vectors $x_j$ ...

  8. Spring注释@Qualifier

    在学习@Autowired的时候我们已经接触到了@Qualifier, 这节就来详细学习一下自定义@Qualifier. 例如定义一个交通工具类:Vehicle,以及它的子类Bus和Sedan. 如果 ...

  9. Zabbix探索:工作时间的设置

    默认情况下,Zabbix的工作时间是启用的. 启用后,图形的北京在工作时间内就是白底的,否则就是灰底的. 今天纠结了半天,因为无论如何都是灰底的. 后来连接到服务器上一看,靠,忘记同步时间了,所以刚好 ...

  10. CCF 认证4

    题意:求强联通分量 Tarjan算法 #include<iostream> #include<stdio.h> #include<stdlib.h> #includ ...