本文主要针对dispatchTouchEvent,onInterceptTouchEvent,onTouchEvent三个方法,通过简单的例子来简单的介绍下。

根据字面意思的理解,dispatchTouchEvent分发触摸事件,onInterceptTouchEvent拦截触摸事件,onTouchEvent触摸事件。正如它们各自的字面意思,下面简单的列出各自的作用和用法。

1、dispatchTouchEvent作用:决定事件是否由onInterceptTouchEvent来拦截处理。

  • 返回super.dispatchTouchEvent时,由onInterceptTouchEvent来决定事件的流向
  • 返回false时,不会继续分发事件,自己内部只处理了ACTION_DOWN
  • 返回true时,不会继续分发事件,自己内部处理了所有事件(ACTION_DOWN,ACTION_MOVE,ACTION_UP)

2、onInterceptTouchEvent作用:拦截事件,用来决定事件是否传向子View

  • 返回true时,拦截后交给自己的onTouchEvent处理
  • 返回false时,拦截后交给子View来处理

3、onTouchEvent作用:事件最终到达这个方法

  • 返回true时,内部处理所有的事件
  • 返回false时,事件会向上传递,由onToucEvent来接受,如果最上面View中的onTouchEvent也返回false的话,那么事件就会消失。
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()处理。

这是摘自网络:

More:

1.  一个事件必然从ACTION_DOWN开始,所以当某一个控件处理了一个ACTION_DOWN事件,可以理解直到下一个ACTION_DOWN之前所有的触摸事件都应当由该控件(target)进行处理。

2.  对于各种listener,显然是由android系统进行处理的。所以Super.onTouchEvent()应当放在子类的该函数的第一行,可以优先保证系统的方法不会被自定义的操作截取而导致没有机会执行。

3.  牢记一个原则,所有的touch事件都是从父容器开始向下传递的,呈U字形

(1)  父容器(类型为 <? Extends ViewGroup>) onInterceptTouchEvent接收到事件,如果return false,转步骤(2),否则转 步骤(3)

(2)  父容器在该位置(ACTION_DOWN发生的位置)存在子控件,如果子控件类型为

<? Extends ViewGroup>,此时该子控件成为父容器,转步骤(1),如果子控件为普通view,即 不是viewgroup的子类,使用子控件转步骤(3),如果不存在子控件,使用父容器转步骤(3)

(3)  该touch事件交给该控件的onTouchEvent进行响应,如果return false,当其存在父容器时,事件传递给父容器,转步骤(3)。当不存在父容器时,该事件被丢弃。如果return true,表示事件被消费了,此touch事件终止。

关于事件传递解释的更好的文章在这里

下面结合具体的例子来讲解,首先是容器类MyLinearLayout继承自LinearLayout,子View类MyTextView继承自TextView。

MyLinearLayout类:

 1 package com.example.time;
2
3 import android.content.Context;
4 import android.util.AttributeSet;
5 import android.util.Log;
6 import android.view.MotionEvent;
7 import android.widget.LinearLayout;
8
9 public class MyLinearLayout extends LinearLayout {
10
11 private String TAB = "MyLinearLayout";
12
13 public MyLinearLayout(Context context, AttributeSet attrs) {
14 super(context, attrs);
15 }
16
17 public MyLinearLayout(Context context) {
18 super(context);
19 }
20
21 @Override
22 public boolean dispatchTouchEvent(MotionEvent ev) {
23 switch(ev.getAction()) {
24 case MotionEvent.ACTION_DOWN:
25 Log.d(TAB, "dispatchTouchEvent action:ACTION_DOWN");
26 break;
27 case MotionEvent.ACTION_UP:
28 Log.d(TAB, "dispatchTouchEvent action:ACTION_UP");
29 break;
30 }
31 return super.dispatchTouchEvent(ev);
32 }
33
34 @Override
35 public boolean onInterceptTouchEvent(MotionEvent ev) {
36 //true表示拦截后交给自己的onTouchEvent处理,false表示传递给子View
37 switch(ev.getAction()) {
38 case MotionEvent.ACTION_DOWN:
39 Log.d(TAB, "onInterceptTouchEvent action:ACTION_DOWN");
40 break;
41 case MotionEvent.ACTION_UP:
42 Log.d(TAB, "onInterceptTouchEvent action:ACTION_UP");
43 break;
44 }
45 return false;
46 }
47
48 @Override
49 public boolean onTouchEvent(MotionEvent event) {
50 switch(event.getAction()) {
51 case MotionEvent.ACTION_DOWN:
52 Log.d(TAB, "---onTouchEvent action:ACTION_DOWN");
53 break;
54 case MotionEvent.ACTION_UP:
55 Log.d(TAB, "---onTouchEvent action:ACTION_UP");
56 break;
57 }
58 return false;
59 }
60 }

MyTextView类:

 1 package com.example.time;
2
3 import android.content.Context;
4 import android.util.AttributeSet;
5 import android.util.Log;
6 import android.view.MotionEvent;
7 import android.widget.TextView;
8
9 public class MyTextView extends TextView {
10
11 private String TAB = "MyTextView";
12
13 public MyTextView(Context context, AttributeSet attrs, int defStyle) {
14 super(context, attrs, defStyle);
15 }
16
17 public MyTextView(Context context, AttributeSet attrs) {
18 super(context, attrs);
19 }
20
21 public MyTextView(Context context) {
22 super(context);
23 }
24
25 @Override
26 public boolean dispatchTouchEvent(MotionEvent event) {
27 switch(event.getAction()) {
28 case MotionEvent.ACTION_DOWN:
29 Log.d(TAB, "dispatchTouchEvent action:ACTION_DOWN");
30 break;
31 case MotionEvent.ACTION_UP:
32 Log.d(TAB, "dispatchTouchEvent action:ACTION_UP");
33 break;
34 }
35 return super.dispatchTouchEvent(event);
36 }
37
38 @Override
39 public boolean onTouchEvent(MotionEvent event) {
40 switch(event.getAction()) {
41 case MotionEvent.ACTION_DOWN:
42 Log.d(TAB, "---onTouchEvent action:ACTION_DOWN");
43 break;
44 case MotionEvent.ACTION_UP:
45 Log.d(TAB, "---onTouchEvent action:ACTION_UP");
46 break;
47 }
48 return false;
49 }
50
51 }

布局文件activity_main.xml

 1 <com.example.time.MyLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
2 android:id="@+id/testview"
3 android:layout_width="fill_parent"
4 android:layout_height="fill_parent"
5 android:gravity="center" >
6 <com.example.time.MyTextView
7 android:layout_width="200dip"
8 android:layout_height="200dip"
9 android:text="@string/hello_world"
10 android:textSize="50sp" />
11 </com.example.time.MyLinearLayout>

为了更清晰的理解事件的分发处理机制,最好自己将上面代码运行一下,主要更改下MyLinearLayout中的onInterceptTouchEvent的返回值(true或false),还有两个类中的onTouchEvent的返回值,来观察logcat中的打印结果,基本上和上面总结出来的一致。

记住一点:true就是自己内部消化掉所有事件,false就是继续传递事件。

[学习总结]5、Android的ViewGroup中事件的传递机制(二)

[学习总结]4、Android的ViewGroup中事件的传递机制(一)的更多相关文章

  1. [学习总结]5、Android的ViewGroup中事件的传递机制(二)

    下面是第一篇的连接 Android的ViewGroup中事件的传递机制(一) 关于onInterceptTouchEvent和onTouchEvent的详细解释. 1 public class Mai ...

  2. Android: 详解触摸事件如何传递

    当视图的层次结构比较复杂的时候,触摸事件的响应流程也变得复杂. 举例来说,你也许有一天想要制作一个手势极其复杂的 Activity 来折磨你的用户,你经过简单思索,认为其中应该包含一个 PageVie ...

  3. Android与javascript中事件分发机制的简单比较

    在前面两篇博客中,我们讨论了Android中的事件分发的相关内容,那么在本篇博客当中,我们就简单探讨一下html或javascript中的事件分发机制,并进行简单的对比. 在前端中,对事件进行绑定有三 ...

  4. android的事件分发传递机制

    事件的分发与传递最重要的三个处理方法是 dispatchTouchEvent onInterceptTouchEvent onTouchEvent 综合来说事件的 传递是由外层向里层传递,而处理是从里 ...

  5. iOS中事件的传递和响应者链条

    在iOS 开发中,常见的事件有三种类型,分别是: (1)触摸事件:平常手指在屏幕上滑动,产生的事件都是触摸事件 (2)加速计事件:微信的摇一摇就是典型的加速计事件 (3)远程控制事件:耳机控制歌曲上一 ...

  6. Android初级教程:单击事件的传递机制初谈

    以上仅是小试牛刀,后续有很多事件传递机制,继续探讨.

  7. Android系统中长按事件的实现机制解析

    在Android的触摸消息中,已经实现了三种监测,它们分别是 1)pre-pressed:对应的语义是用户轻触(tap)了屏幕 2)pressed:对应的语义是用户点击(press)了屏幕 3)lon ...

  8. Android笔记——Activity中的数据传递案例(用户注冊)

    1.创建程序activity_main: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/andro ...

  9. 【Android】Intent中使用Extra传递数据

    传值方法一 Intent intent = new Intent(); Bundle bundle = new Bundle(); //该类用作携带数据 bundle.putString(" ...

随机推荐

  1. CentOS7 安装oracle 11g (11.2.0.1.0)

    1.安装依赖: #yum -y install binutils compat-libcap1 compat-libstdc++-33 gcc gcc-c++ glibc glibc-devel ks ...

  2. 攻防世界 Misc 新手练习区 stegano CONFidence-DS-CTF-Teaser Writeup

    攻防世界 Misc 新手练习区 stegano CONFidence-DS-CTF-Teaser Writeup 题目介绍 题目考点 隐写术 摩斯密码 Writeup 下载附件是PDF文件打开,研究一 ...

  3. 使用python操作HDF5文件

    HDF Hierarchical Data Format,又称HDF5 在深度学习中,通常会使用巨量的数据或图片来训练网络.对于如此大的数据集,如果对于每张图片都单独从硬盘读取.预处理.之后再送入网络 ...

  4. 'pybot' 不是内部或外部命令,也不是可运行的程序 或批处理文件

    在dos下运行pybot --version提示不是内部命令 这是pip list 打印信息: 解决方法: 在python/Scripts目录下加一个pybot.bat 文件 内容为: @Echo o ...

  5. uni-app app端设置全屏背景色

    设置page:{样式},博主调试的时候在app端不起作用,设置配置文件的backgroundColor也没有用,所以博主就使用了一个稍微比较偏的办法解决了,没有用获取设备信息的api来实现 具体操作就 ...

  6. webpack 之开发环境优化 source-map

    webpack 之开发环境优化 source-map /** * source-map:一种 提供源代码到构建后代码映射 技术 (如果构建后代码出错了,通过映射可以追踪源代码错误) * [inline ...

  7. Python 数据类型常用的内置方法(二)

    目录 Python 数据类型常用的内置方法(二) 1.字符串类型常用内置方法 1.upper.lower.isupper.islower 2.startswith.endswith 3.format ...

  8. [cf1178G]The Awesomest Vertex

    2020年论文题,这里给出了一个$o(n\log^{2}n+m\log^{3}n)$的做法,例题3即为原题 1.例题1 题面 给定$n$个一次函数$f_{i}(x)$,$m$次查询$F(x)=\max ...

  9. 收集的常用的CTF学习资源网站

    http://www.sec-wiki.com/skill/        安全技能学习路线(迷茫就看它) https://wiki.x10sec.org/       介绍了CTF各个方向的基础知识 ...

  10. CF1477A Nezzar and Board

    考虑 \(2x - y\) 我们改为 \(x + (x - y)\) 是一个更好的形式. 我们可以表示一个数为\(x_i + \sum_{j,k}(x_j - x_k) = K\) 我们考虑移到 \( ...