首先,看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. C、C++中“*”操作符和“后++”操作符的优先级

    假设有如下的定义 char carr[] = {"test"}; char cp = carr; 那么表达式 *cp++; 的右值是什么呢? 这个表达式在数组遍历的程序中非常常见, ...

  2. HDU 5091 线段树扫描线

    给出N个点.和一个w*h的矩形 给出N个点的坐标,求该矩形最多能够覆盖多少个点 对每一个点point(x.y)右边生成相应的点(x+w,y)值为-1: 纵向建立线段树,从左到右扫描线扫一遍.遇到点则用 ...

  3. for语句之侦查队挑选人、猴子吃桃、5个小朋友算年龄、1 () 2 () 3 ()4 = 4;问括号里我要填 (- 或 +)问题

    1.某侦察队接到一项紧急任务,要求在A.B.C.D.E.F六个队员中尽可能多地挑若干人,但有以下限制条件:侦察兵A和B两人中至少去一人: a+b>=1(由于每个队员有两种状态:去与不去,假设不去 ...

  4. Jquery - checked 全选与取消全选

    html: <!DOCTYPE html> <html> <head> <title>节点列表</title> <link rel=& ...

  5. iOS UISearchBar UISearchController

    搜索栏的重要性我们就不说了,狼厂就是靠搜索起家的,现在越来越像一匹没有节操的狼,UC浏览器搜索栏现在默认自家的神马搜索,现在不管是社 交,O2O还是在线教育等都会有一个搜索栏的实现,不过彼此实现效果是 ...

  6. [Swust OJ 1125]--又见GCD(数论,素数表存贮因子)

    题目链接:http://acm.swust.edu.cn/problem/1125/ Time limit(ms): 1000 Memory limit(kb): 65535   Descriptio ...

  7. java数组中的三种排序方法中的冒泡排序方法

    我记得我大学学java的时候,怎么就是搞不明白这三种排序方法,也一直不会,现在我有发过来学习下这三种方法并记录下来. 首先说说冒泡排序方法:冒泡排序方法就是把数组中的每一个元素进行比较,如果第i个元素 ...

  8. if…else…if…else…

    参见以前做过的练习一元二次方程 #include <stdio.h> #include <math.h> /* 一元二次方程的标准形式:ax2+bx+c=0 a,b,c为常数, ...

  9. 面向对象程序设计-C++ Type conversion (Static) & Inheritance & Composition【第十二次上课笔记】

    这节课继续讲解了 static 作为静态数据成员 / 成员函数的用法 具体详解我都已注释出来了,大家可以慢慢看 有任何问题都可以在这篇文章下留言我会及时解答 :) //static 静态数据成员 // ...

  10. MVC 扩展 Html.ImageFor

    Asp.Net MVC 扩展 Html.ImageFor 方法详解 背景: 在Asp.net MVC中定义模型的时候,DataType有DataType.ImageUrl这个类型,但htmlhelpe ...