首先,看Android的官方文档正解

onInterceptTouchEvent()与onTouchEvent()的机制:

  1. down事件首先会传递到onInterceptTouchEvent()方法

  2. 如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return false,

  那么后续的move, up等事件将继续会先传递给该ViewGroup,之后才和down事件一样传递给最

  终的目标view的onTouchEvent()处理

  3. 如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return true,

  那么后续的move, up等事件将不再传递给onInterceptTouchEvent(),而是和down事件一样

  传递给该ViewGroup的onTouchEvent()处理,注意,目标view将接收不到任何事件。

  4. 如果最终需要处理事件的view的onTouchEvent()返回了false,那么该事件将被传递至其上一

  层次的view的onTouchEvent()处理

  5. 如果最终需要处理事件的view 的onTouchEvent()返回了true,那么后续事件将可以继续传递

  给该view的onTouchEvent()处理

这是官方文档的说法,要是自己没亲自去写个程序观察哈,基本上没法理解,所以上程序先,然后分析:

布局文件main.xml

  1. <span style="font-size: small;"><?xml version="1.0" encoding="utf-8"?>
  2. <com.hao.LayoutView1 xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:orientation="vertical" android:layout_width="fill_parent"
  4. android:layout_height="fill_parent">
  5. <com.hao.LayoutView2
  6. android:orientation="vertical" android:layout_width="fill_parent"
  7. android:layout_height="fill_parent" android:gravity="center">
  8. <com.hao.MyTextView
  9. android:layout_width="wrap_content" android:layout_height="wrap_content"
  10. android:id="@+id/tv" android:text="AB" android:textSize="40sp"
  11. android:textStyle="bold" android:background="#FFFFFF"
  12. android:textColor="#0000FF" />
  13. </com.hao.LayoutView2>
  14. </com.hao.LayoutView1>
  15. </span>

第一层自定义布局LayoutView1.java

  1. <span style="font-size: small;">package com.hao;
  2. import android.content.Context;
  3. import android.util.AttributeSet;
  4. import android.util.Log;
  5. import android.view.MotionEvent;
  6. import android.widget.LinearLayout;
  7. public class LayoutView1 extends LinearLayout {
  8. private final String TAG = "LayoutView1";
  9. public LayoutView1(Context context, AttributeSet attrs) {
  10. super(context, attrs);
  11. Log.e(TAG,TAG);
  12. }
  13. @Override
  14. public boolean onInterceptTouchEvent(MotionEvent ev) {
  15. int action = ev.getAction();
  16. switch(action){
  17. case MotionEvent.ACTION_DOWN:
  18. Log.e(TAG,"onInterceptTouchEvent action:ACTION_DOWN");
  19. //              return true; 在这就拦截了,后面的就不会得到事件
  20. break;
  21. case MotionEvent.ACTION_MOVE:
  22. Log.e(TAG,"onInterceptTouchEvent action:ACTION_MOVE");
  23. break;
  24. case MotionEvent.ACTION_UP:
  25. Log.e(TAG,"onInterceptTouchEvent action:ACTION_UP");
  26. break;
  27. case MotionEvent.ACTION_CANCEL:
  28. Log.e(TAG,"onInterceptTouchEvent action:ACTION_CANCEL");
  29. break;
  30. }
  31. return false;
  32. }
  33. @Override
  34. public boolean onTouchEvent(MotionEvent ev) {
  35. int action = ev.getAction();
  36. switch(action){
  37. case MotionEvent.ACTION_DOWN:
  38. Log.e(TAG,"onTouchEvent action:ACTION_DOWN");
  39. break;
  40. case MotionEvent.ACTION_MOVE:
  41. Log.e(TAG,"onTouchEvent action:ACTION_MOVE");
  42. break;
  43. case MotionEvent.ACTION_UP:
  44. Log.e(TAG,"onTouchEvent action:ACTION_UP");
  45. break;
  46. case MotionEvent.ACTION_CANCEL:
  47. Log.e(TAG,"onTouchEvent action:ACTION_CANCEL");
  48. break;
  49. }
  50. return true;
  51. //         return false;
  52. }
  53. @Override
  54. protected void onLayout(boolean changed, int l, int t, int r, int b) {
  55. // TODO Auto-generated method stub
  56. super.onLayout(changed, l, t, r, b);
  57. }
  58. @Override
  59. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  60. // TODO Auto-generated method stub
  61. super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  62. }
  63. }</span>

第二层布局LayoutView2.java

  1. <span style="font-size: small;">package com.hao;
  2. import android.content.Context;
  3. import android.util.AttributeSet;
  4. import android.util.Log;
  5. import android.view.MotionEvent;
  6. import android.widget.LinearLayout;
  7. public class LayoutView2 extends LinearLayout {
  8. private final String TAG = "LayoutView2";
  9. public LayoutView2(Context context, AttributeSet attrs) {
  10. super(context, attrs);
  11. Log.e(TAG,TAG);
  12. }
  13. @Override
  14. public boolean onInterceptTouchEvent(MotionEvent ev) {
  15. int action = ev.getAction();
  16. switch(action){
  17. case MotionEvent.ACTION_DOWN:
  18. Log.e(TAG,"onInterceptTouchEvent action:ACTION_DOWN");
  19. //           return true;
  20. break;
  21. case MotionEvent.ACTION_MOVE:
  22. Log.e(TAG,"onInterceptTouchEvent action:ACTION_MOVE");
  23. break;
  24. case MotionEvent.ACTION_UP:
  25. Log.e(TAG,"onInterceptTouchEvent action:ACTION_UP");
  26. break;
  27. case MotionEvent.ACTION_CANCEL:
  28. Log.e(TAG,"onInterceptTouchEvent action:ACTION_CANCEL");
  29. break;
  30. }
  31. return false;
  32. }
  33. @Override
  34. public boolean onTouchEvent(MotionEvent ev) {
  35. int action = ev.getAction();
  36. switch(action){
  37. case MotionEvent.ACTION_DOWN:
  38. Log.e(TAG,"onTouchEvent action:ACTION_DOWN");
  39. break;
  40. case MotionEvent.ACTION_MOVE:
  41. Log.e(TAG,"onTouchEvent action:ACTION_MOVE");
  42. break;
  43. case MotionEvent.ACTION_UP:
  44. Log.e(TAG,"onTouchEvent action:ACTION_UP");
  45. break;
  46. case MotionEvent.ACTION_CANCEL:
  47. Log.e(TAG,"onTouchEvent action:ACTION_CANCEL");
  48. break;
  49. }
  50. //       return true;
  51. return false;
  52. }
  53. }
  54. </span>

自定义MyTextView.java

  1. <span style="font-size: small;">package com.hao;
  2. import android.content.Context;
  3. import android.util.AttributeSet;
  4. import android.util.Log;
  5. import android.view.MotionEvent;
  6. import android.view.View;
  7. import android.widget.TextView;
  8. public class MyTextView extends TextView {
  9. private final String TAG = "MyTextView";
  10. public MyTextView(Context context, AttributeSet attrs) {
  11. super(context, attrs);
  12. Log.e(TAG,TAG);
  13. }
  14. @Override
  15. public boolean onTouchEvent(MotionEvent ev) {
  16. int action = ev.getAction();
  17. switch(action){
  18. case MotionEvent.ACTION_DOWN:
  19. Log.e(TAG,"onTouchEvent action:ACTION_DOWN");
  20. break;
  21. case MotionEvent.ACTION_MOVE:
  22. Log.e(TAG,"onTouchEvent action:ACTION_MOVE");
  23. break;
  24. case MotionEvent.ACTION_UP:
  25. Log.e(TAG,"onTouchEvent action:ACTION_UP");
  26. break;
  27. case MotionEvent.ACTION_CANCEL:
  28. Log.e(TAG,"onTouchEvent action:ACTION_CANCEL");
  29. break;
  30. }
  31. return false;
  32. //       return true;
  33. }
  34. public void onClick(View v) {
  35. Log.e(TAG, "onClick");
  36. }
  37. public boolean onLongClick(View v) {
  38. Log.e(TAG, "onLongClick");
  39. return false;
  40. }
  41. }
  42. </span>

其实代码很简单,就是自定义了View,在View里面都重写了interceptTouchEvnet (),和onTouchEvent(),然后测试其返回值,对监听的影响,关键是自己动手,逐个测试,并预测结果,等你能预测结果的时候,也就懂了,需要修改的地方就是interceptTouchEvnet 和onTouchEvent的返回值,他们决定了事件监听的流程,下面我画了一张图,如有不足之处欢迎指正,谢谢!

下面是我的正解:

基本的规则是: 
      *1.down事件首先会传递到onInterceptTouchEvent()方法 
      * 
      * 2.如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return false(不拦截),
      * 那么后续的move, up等事件将继续会先传递给该ViewGroup,之后才和down事件一样传递给最终的目标view的onTouchEvent()处理。 
      *
      * 3.如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return true(拦截,那么后面的move,up事件不需要在看因为已经拦截了, 我们直接拿去处理onTouchEvent()就可以了),那么后续的move, up等事件将不再传递给onInterceptTouchEvent(), 而是和down事件一样传递给该ViewGroup的onTouchEvent()处理,注意,目标view将接收不到任何事件。 下面例子演示:
      * 1:LayoutView1(31375): onInterceptTouchEvent action:ACTION_DOWN
      * 2:LayoutView2(31375): onInterceptTouchEvent action:ACTION_DOWN
      * 3:LayoutView2(31375): onTouchEvent action:ACTION_DOWN
      * 4:LayoutView1(31375): onInterceptTouchEvent action:ACTION_MOVE
      * 5:LayoutView2(31375): onTouchEvent action:ACTION_MOVE
      * 6:LayoutView1(31375): onInterceptTouchEvent action:ACTION_MOVE
      * 7:LayoutView2(31375): onTouchEvent action:ACTION_MOVE
      * 8:LayoutView1(31375): onInterceptTouchEvent action:ACTION_UP
      * 9:LayoutView2(31375): onTouchEvent action:ACTION_UP
      * 该设置为:
      * onInterceptTouchEvent:LayoutView1为false,LayoutView2为true
      * onTouchEvent:LayoutView2为true
      * 故而事件在LayoutView2(onInterceptTouchEvent:返回true)时被拦截并处理,根据上面说法就是LayoutView2后续的MOVE,UP操作都不在经过onInterceptTouchEvent,直接
      * 交给onTouchEvent处理,结果也的确如此。(见:LayoutView2的3,5,7,9,第一次是onInterceptTouchEvent处理如1,以后交给onTouchEvent)
      * 而LayoutView1都还是要经过onInterceptTouchEvent(见LayoutView1的4,6,8)
      * 
      * 4.如果最终需要处理事件的view的onTouchEvent()返回了false(没能处理这个事件,不能丢在传回来让父继续),
      * 那么该事件将被传递至其上一层次的view的onTouchEvent()处理。 
      * **************************************************************************
      * 感觉像是一个圈,然后一直在找一个能处理这个消息的人,如果找到了就结束,没找到就循环,直到回到发出消息的那个人
      * 注(对下面):没有标注的DOWN表示拦截事件onInterceptTouchEvent,标注了onTouchEvent就是处理事件
      * a.如果都没处理(onInterceptTouchEvent返回false):
A(DOWN)-->B(DOWN)-->C(onTouchEvent DOWN)-->B(onTouchEvent DOWN)-->A(onTouchEvent DOWN),没有执行UP事件,注意有MOVE的话,在DOWN和UP之间,下面的都一样。
      *b. B处理(B的onInterceptTouchEvent返回true):
A(DOWN)-->B(DOWN)-->B(onTouchEvent)-->A(onTouchEvent UP)-->B(onTouchEvent UP)-->(over)
      *
形象说明:如果父亲不拦截消息就传给儿子,如果儿子要这个消息就处理(DOWN),结束,然后有父亲1--父亲2--儿子以此释放消息(UP)。 然是如果儿子对这个消息置之不理,那这个消息又传回父亲,由父亲来处理即。
 
下面给出了5中情况(不拦截表示onInterceptTouchEvent返回false):
      * 11** 父亲1(LayoutView1不拦截false)---父亲2(LayoutView2不拦截false)--儿子(MyTextView,onTouchEvent return true)--结束
      * 22** 父亲1(LayoutView1不拦截false)---父亲2(LayoutView2不拦截false)--儿子(MyTextView,onTouchEvent return false)--回传给父亲2(onTouchEvent return true)--结束
      * 33** 父亲1(LayoutView1不拦截false)---父亲2(LayoutView2不拦截false)--儿子(MyTextView,onTouchEvent return false)--回传给父亲2(onTouchEvent return false)--父亲1(onTouchEvent return true)--结束(如果都没处理不在执行UP ACTION)
      * 44** 父亲1(LayoutView1拦截true)--父亲1(onTouchEvent return true)--结束          (DOWN--DOWN(onTouchEvent)--UP(onTouchEvent))
      * 55** 父亲1(LayoutView1拦截false)--父亲2(LayoutView2拦截true)--父亲2(onTouchEvent return false)--父亲1(onTouchEvent return true)--结束      (DOWN1--DOWN2--DOWN(2 onTouchEvent)--DOWN(1 onTouchEvent)--UP(1 onTouchEvent))(1:父亲2,2:父亲2)
      * 
      * ***************************************************************************
      * 5.如果最终需要处理事件的view 的onTouchEvent()返回了true,那么后续事件将可以继续传递给该view的onTouchEvent()处理。 
      */
 
下面给出一张处理的流程图:

 下附源代码:

Android事件模型之interceptTouchEvnet ,onTouchEvent关系正解的更多相关文章

  1. Android 事件模型

    本文内容 基于监听的事件模型 基于回调的事件模型 Android 支持两种事件模型,基于监听的事件模型和基于回调的事件模型. 基于监听的事件模型 基于监听的事件模型是一种委托式的,更"面向对 ...

  2. Android事件机制之二:onTouch详解

    <Android事件机制之一:事件传递和消费>一文总结了Android中的事件传递和消费机制. 在其中对OntachEvent中的总结中,不是很具体.本文将主要对onTach进行总结. o ...

  3. 对于android触摸事件模型的一些理解

    body{ font-family: "Microsoft YaHei UI","Microsoft YaHei",SimSun,"Segoe UI& ...

  4. Android进阶——Android事件分发机制之dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent

    Android事件分发机制可以说是我们Android工程师面试题中的必考题,弄懂它的原理是我们避不开的任务,所以长痛不如短痛,花点时间干掉他,废话不多说,开车啦 Android事件分发机制的发生在Vi ...

  5. 【朝花夕拾】Android自定义View篇之(六)Android事件分发机制(中)从源码分析事件分发逻辑及经常遇到的一些“诡异”现象

    前言 转载请注明,转自[https://www.cnblogs.com/andy-songwei/p/11039252.html]谢谢! 在上一篇文章[[朝花夕拾]Android自定义View篇之(五 ...

  6. 【朝花夕拾】Android自定义View篇之(五)Android事件分发机制(上)Touch三个重要方法的处理逻辑

    前言 转载请注明,转自[https://www.cnblogs.com/andy-songwei/p/10998855.html]谢谢! 在自定义View中,经常需要处理Android事件分发的问题, ...

  7. Android事件分发机制三:事件分发工作流程

    前言 很高兴遇见你~ 本文是事件分发系列的第三篇. 在前两篇文章中,Android事件分发机制一:事件是如何到达activity的? 分析了事件分发的真正起点:viewRootImpl,Activit ...

  8. Android事件分发机制四:学了事件分发有什么用?

    " 学了事件分发,影响我CV大法吗?" " 影响我陪女朋友的时间" " ..... " 前言 Android事件分发机制已经来到第四篇了,在 ...

  9. 讲讲Android事件拦截机制

    简介 什么是触摸事件?顾名思义,触摸事件就是捕获触摸屏幕后产生的事件.当点击一个按钮时,通常会产生两个或者三个事件--按钮按下,这是事件一,如果滑动几下,这是事件二,当手抬起,这是事件三.所以在And ...

随机推荐

  1. js中访问对象的方法

    如果在js中定义了一个变量obj1,如 var obj1 = 234; 那么访问这个边个两的方式至少有两种, 1 window["obj1"],那么值为234, 2 var tar ...

  2. php随笔9-thinkphp OA系统 集成UEditor

    版本信息:thinkphp 3.1.3 full     UEditor 1.4.3.1 utf8-php 1.将EUditor放在项目public目录下. 2.在指定页面加载编辑器 <!-- ...

  3. oracle 开发笔记“跨数据库查询复制”

    1.方法一:创建DBL(data base link) CREATE PUBLIC DATABASE LINK 数据链名称 CONNECT TO 登陆用户名 IDENTIFIED BY 密码 USIN ...

  4. openrisc 之 Wishbone总线学习笔记——总线互联

    一,总线命名规范 1,wishbone总线接口信号都是高电平有限 2,wishbone接口信号都是以 _i ,或者是 _o 结束.i表示输入, o表示输出. ()表示该信号为总线信号,总线位宽可以大于 ...

  5. openrisc 之 Wishbone总线学习笔记——总线特性

    特性: 一,互联方式: 支持点到点.共享总线.十字交叉(Crossbar)和基于交换结构(Switch fabric)的互联. 二,数据操作方式:单次读/写操作.块读/写操作,读改写(RMW,Read ...

  6. 利用Adapter对象将数据填充到DataTable(或DataSet)的例子

    前: <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="DataAdapter ...

  7. 省部级干部list

    省部级干部表 省(市.自治区) 省(市)委书记 省(市)人大主任 省(市)长 省(市)政协主席 北京市 郭金龙 杜德印 王安顺 吉林 天津市 黄兴国 肖怀远 黄兴国 臧献甫 上海市 韩正 殷一璀(女) ...

  8. 解题报告 HDU1789 Doing Homework again

    Doing Homework again Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64 ...

  9. ZigBee研究之旅(二)

    在学习ZigBee设备CC2530模块时,编程后程序无法运行,但又十分确定程序的真确性的情况下,看看是不是project栏下的option选项配置的有问题,我是经常在这里出问题,一开始找不到原因,特此 ...

  10. ContentProvider的一些总结

    ContentProvider中的URI, The URI that identifies the provider   一个特定的uri对应着唯一一个内容提供者, 谷歌官方文档里的说明, Query ...