本文主要针对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. 基于Dapr的 Azure 容器应用

    微软在 Ignite 2021 大会上发布了预览版的Azure Container Apps,这是一个完全托管的无服务器容器运行时间,用于大规模构建和运行现代应用程序.从2021 年 11 月 2 日 ...

  2. 连接url

    celery broker redis with password broker_url = 'redis://user:password@redishost:6379/0' tooz zookeep ...

  3. webRTC中语音降噪模块ANS细节详解(四)

    上篇(webRTC中语音降噪模块ANS细节详解(三))讲了噪声的初始估计方法以及怎么算先验SNR和后验SNR. 本篇开始讲基于带噪语音和特征的语音和噪声的概率计算方法和噪声估计更新以及基于维纳滤波的降 ...

  4. 大爽Python入门教程 2-3 字符串,列表,字典

    大爽Python入门公开课教案 点击查看教程总目录 除了通用的序列方法, 列表和字符串还有些自己的专属方法. 后面介绍有些是英中文对照介绍(英文来自官方文档), 便于大家更深入的去理解其意思. 灵活的 ...

  5. [cf1515H]Phoenix and Bits

    记$V=2^{20}-1$,即值域范围,也可以作为"全集" 显然与$a_{i}$的顺序无关,对所有$a_{i}$维护一棵trie树 关于如何维护这棵trie树,考虑使用分裂+合并的 ...

  6. 没有人比我更会使用集合!对, 是dart中的集合

    目录 简介 List的使用 Set的使用 Map的使用 常见的集合方法 总结 简介 dart中的集合有三个,分别是list,set和map.dart在dart:core包中提供了对于这三种集合非常有用 ...

  7. asList和subList的缺陷

    概述 在开发中我们经常使用asList去把一个数组转换为List.也存在通过subList.subMap.来对List.Map.Set来进行类似使用subString方法来对String对象进行分割处 ...

  8. layui页面操作,点击一个添加页面,跳转有确定,然后点击确定后将选择的几个数据返回前一个页面获取值,然后ajax请求后台

    custUserIndex.html [添加页面代码] <!DOCTYPE html> <html> <head> <meta charset="u ...

  9. 应用程序池自动停止,事件查看器报错6D000780

    20210913 今天中午网站突然报错,后台程序无法访问,503错误. 调查发现"应用程序池"被关闭,但是手动开启后不久,又被关闭. 本地调试没问题,所以一开始怀疑是服务器或者Ng ...

  10. Codeforces 1368H - Breadboard Capacity(最小割+线段树维护矩阵乘法)

    Easy version:Codeforces 题面传送门 & 洛谷题面传送门 Hard version:Codeforces 题面传送门 & 洛谷题面传送门 首先看到这种从某一种颜色 ...