一个最简单的屏幕触摸动作触发了一系列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 的话,这个事件就会“消失”,而且接收不到下一次事件。

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

layout配置文件 main.xml:

  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代码:

  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 dispatchTouchEvent介绍的更多相关文章

  1. android Animation介绍

    Animation介绍: 在Android SDK介绍了2种Animation模式: 1. Tween Animation:间动画,通过对场景里的对象不断做图像变换(平移.缩放.旋转)产生动画效果,即 ...

  2. android AsyncTask介绍(转)

    android AsyncTask介绍 AsyncTask和Handler对比 1 ) AsyncTask实现的原理,和适用的优缺点 AsyncTask,是android提供的轻量级的异步类,可以直接 ...

  3. Android monkey介绍

    Android monkey介绍 原文地址 1 简略 monkey是android下自动化测试比较重要的的一个工具,该工具可以运行在host端或者设备(模拟器或真实设备).它会向系统发送随机事件流(即 ...

  4. [Learn Android Studio 汉化教程]第一章 : Android Studio 介绍

    注:为了看上去比较清晰这里只转载了中文 原地址:  [Learn Android Studio 汉化教程]第一章 : Android Studio 介绍 本章将引导您完成安装和设置开发环境,然后你就可 ...

  5. 【转】Android bluetooth介绍(三): 蓝牙扫描(scan)设备分析

    原文网址:http://blog.csdn.net/xubin341719/article/details/38584469 关键词:蓝牙blueZ  A2DP.SINK.sink_connect.s ...

  6. Android bluetooth介绍(四): a2dp connect流程分析

    关键词:蓝牙blueZ  A2DP.SINK.sink_connect.sink_disconnect.sink_suspend.sink_resume.sink_is_connected.sink_ ...

  7. android动画介绍之 自己定义Animation动画实现qq抖一抖效果

    昨天我们介绍了Animation的基本使用方法.小伙伴们了解的怎么样了?假设还没有了解过Animation的小伙伴能够看看这篇博客 android动画介绍--Animation 实现loading动画 ...

  8. android动画介绍之 自定义Animation动画实现qq抖一抖效果

    昨天我们介绍了Animation的基本用法.小伙伴们了解的怎么样了?如果还没有了解过Animation的小伙伴可以看看这篇博客 android动画介绍--Animation 实现loading动画效果 ...

  9. android动画介绍--Animation 实现loading动画效果

    Animation的使用方法并不难.这里简单的介绍一下使用方法. 先看效果图: 效果还是不错的吧. 下面来看看使用方法. 动画效果是通过Animation来实现的,一共有四种,分别为: AlphaAn ...

随机推荐

  1. ios7中的多任务

    转自:http://onevcat.com/2013/08/ios7-background-multitask/ WWDC 2013 Session笔记 - iOS7中的多任务 iOS7的后台多任务特 ...

  2. git 创建版本库

    服务器安装后git后 1.在repositories仓库文件夹中执行git init aa.git --bare  创建aa的中心库(注意建立aa版本库时当前登录用户必须为git的相关用户,并保证/d ...

  3. jQuery 实现菜单

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  4. css3基础教程:CSS3弹性盒模型

    今天给大家分享一篇关于CSS3基础教程 文章,主要是讲CSS3弹性盒模型.弹性布局的主要思想是让容器有能力来改变项目的宽度和高度,以填满可用空间(主要是为了容纳所有类型的显示设备和屏幕尺寸)的能力. ...

  5. Android RecyclerView单击、长按事件标准实现:基于OnItemTouchListener + GestureDetector

     Android RecyclerView单击.长按事件:基于OnItemTouchListener + GestureDetector标准实现 Android RecyclerView虽然拥有L ...

  6. Android Priority Job Queue (Job Manager):多重不同Job并发执行并在前台获得返回结果(四)

     Android Priority Job Queue (Job Manager):多重不同Job并发执行并在前台获得返回结果(四) 在Android Priority Job Queue (Jo ...

  7. solr异常解决

    使用solr1.4跟solr3.1时,配置了个唯一id类型是sint 或者int,启动时在tomcat后台就会抛出这个异常: org.apache.solr.common.SolrException: ...

  8. 根据滑动显隐状态栏的iOS实现

    之前很多兄弟问如何实现类似于淘宝客户端搜索列表那种动态显隐的效果,这几天刚好有时间,就实现了几个例子搞一下,其实原理很简单,也参考了github上一位兄弟的实现.不多说,上代码 @interface ...

  9. 初次学习c语言

    #include<stdio.h> main(){      int o,p,q; scanf("%d%d",&o,&p); q=o+p; printf ...

  10. viewpager接受值图片轮播

    package com.baway.test; import java.util.ArrayList;import java.util.List;import java.util.Timer;impo ...