Android Touch事件原理加实例分析

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事件原理加实例分析

时间: 2024-11-03 05:40:19

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

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

Native原生相比于Hybrid或H5最大优点是具有流畅和复杂的交互效果,触摸事件便是其中重要一项,包括点击(Click).长按(LongClick).手势(gesture)等. 以最简单常见的点击(Click)为例,Native组件可以自定义selector,使得被点击的组件具有动态效果,Android 5.0以上甚至可以有涟漪效果(Material Design).而这些在Hybrid或H5中很难实现,很多时候区分它们与原生最简单的方法就是检验点击交互效果. React-Native的强大

Android Touch事件分发过程

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

Android touch事件的派发流程

http://blog.csdn.net/xyz_lmn/article/details/12517911 通过流程图了解touch事件派发过程. http://blog.csdn.net/stonecao/article/details/6759189 从代码的层面分析,尽管目前代码已经变化了,但是作者的分析对Android touch事件派发流程的理解还是很有帮助的. http://www.2cto.com/kf/201504/388625.html 通过实例了解Button的touch事件

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

转载于:http://blog.csdn.net/yuanzeyao/article/details/38025165 在前一篇文章中,我主要讲解了Android源码中的Touch事件的传递过程,现在我想使用一个demo以及一个实例来学习一下Andorid中的Touch事件处理过程. 在Android系统中,和Touch事件分发和处理紧密相关的三个函数如下:(1) public boolean dispatchTouchEvent(MotionEvent ev)(2) public boolea

Android Touch事件传递机制详解 下

尊重原创:http://blog.csdn.net/yuanzeyao/article/details/38025165 资源下载:http://download.csdn.net/detail/yuanzeyao2008/7660997 在前一篇文章中,我主要讲解了Android源码中的Touch事件的传递过程,现在我想使用一个demo以及一个实例来学习一下Andorid中的Touch事件处理过程. 在Android系统中,和Touch事件分发和处理紧密相关的三个函数如下:(1) public

Android Touch事件分发详解

Android Touch事件分发详解 先说一些基本的知识,方便后面分析源码时能更好理解. - 所有Touch事件都被封装成MotionEvent对象,包括Touch的位置.历史记录.第几个手指等. 事件类型分为ACTION_DOWN,ACTION_UP,ACTION_MOVE,ACTION_POINTER_DOWN,ACTION_POINTER_UP,ACTION_CANCEL, 每个 一个完整的事件以ACTION_DOWN开始ACTION_UP结束,并且ACTION_CANCEL只能由代码引

【转】Android Touch事件传递机制解析

原文地址:http://www.cnblogs.com/runssnail/p/4250549.html 说明:本文在原文地址上有所改动 一.小故事 在讲正题之前我们讲一段有关任务传递的小故事,抛砖迎玉下: 话说一家软件公司,来一个任务,分派给了开发经理去完成 开发经理拿到,看了一下,感觉好简单,于是 开发经理:分派给了开发组长 开发组长:分派给了自己组员(程序员) 程序员:分派给了自己带的实习生. 实习生:好苦逼,无法分派,怎么办啊?只能自己干了 但是实习生能不能做好,有两种情况了. 情况一:

Android Touch事件传递机制详解 上

尊重原创:http://blog.csdn.net/yuanzeyao/article/details/37961997 最近总是遇到关于Android Touch事件的问题,如:滑动冲突的问题,以前也花时间学习过Android Touch事件的传递机制,可以每次用起来的时候总是忘记了,索性自己总结一下写篇文章避免以后忘记了,其实网上关于Touch事件的传递的文章真的很多,但是很少有系统性的,都是写了一个简单的demo运行了一下,对于我们了解Android Touch事件基本上没有任何帮助. 今

Android touch 事件传递机制

前言: (1)在自定义view的时候经常会遇到事件拦截处理,比如在侧滑菜单的时候,我们希望在侧滑菜单里面有listview控件,但是我们希望既能左右滑动又能上下滑动,这个时候就需要对触摸的touch事件进行拦截.这个时候我们就需要明白android touch 事件传递机制, (2)以前很多时候比较模糊,也许是网上看到也有很多事件传递的相关文章,但我看着头晕,解释不彻底,有的说得一半,总算不满足不满意,于是据我自己的理解来彻底的来整理下具体的是怎么个传递方式,分享给大家,希望大家看到有什么不对的