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. bzoj2245

    这道题还是比较简单的费用流,由于w是递增的 实际上,这题数据还可以强一点,比如说分段函数不保证费用递增, 就要加一点技巧了(要保证函数的顺序) ; type node=record        ne ...

  2. UVa 140 (枚举排列) Bandwidth

    题意较复杂,请参见原题=_=|| 没什么好说的,直接枚举每个排列就好了,然后记录最小带宽,以及对应的最佳排列. STL里的next_permutation函数真是好用. 比较蛋疼的就是题目的输入了.. ...

  3. js判断checkbox是否已选

    代码: <h2>Default</h2> @using (Html.BeginForm()) { <ul> <li>@Html.CheckBox(&qu ...

  4. DbHelper and OracleHelper

    1 连接Sql Server的ConnectionString: Data Source=.;Initial Catalog=ViewVideo;User ID=sa;Password=XXXXXX; ...

  5. Peer to Peer File Sharing Through WCF

    http://www.codeproject.com/Articles/614028/Peer-to-Peer-File-Sharing-Through-WCF https://github.com/ ...

  6. win7(64位)+IE8+QC9.0

    环境win7(64位)+IE8+QC9.0出现的问题IE8访问QC9.0有时访问登录显示正常,但是有时访问QC页面无法显示正常,然后在ie8中安全中设置“启用内存保护帮助减少联机攻击*”也无法找到该项 ...

  7. opencv开发的程序分发给客户时所需要的dll文件

    这里主要讲在其他裸机,没有搭建开发环境机器上运行自己开发的程序. 为了测试,我专门用visualbox搭建了一个虚拟机(主机和虚拟机都是win7系统) 在发给别人程序运行出现错误:msvcp100d. ...

  8. wuzhicms 模块开发

    首先,模块开发需要了解五指cms的目录结构: 然后,我们需要新增加一个模块目录: 再app下面创建 如:content 下面包含文件: 前台文件的创建: 看下 index.php 的内容: <? ...

  9. bzoj 1835 [ZJOI2010]base 基站选址(DP+线段树)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1835 [题意] 有n个村庄,每个村庄位于d[i],要求建立不多于k个基站,在第i个村庄 ...

  10. shark错误:Query returned non-zero code: -101

      环境:shark(0.11分支编译)+spark 0.8+hive 0.11(编译)+hadoop 2.00 cdh4.4 用sharkserver的方式执行一段时间后,通过kit-b8连接到ki ...