本文主要针对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. 【Go语言学习笔记】Go的函数

    函数还是这几块: 参数 返回值 作用域 执行顺序 参数和返回值 func FuncName(/*参数列表*/) (o1 type1, o2 type2/*返回类型*/) { //函数体 return ...

  2. mongodb安装教程(一)

    版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/fengtingYan/article/de ...

  3. JMeter学习笔记--并发登录测试

    账号密码读取文件 1.设置线程数为30,并发用户量就是30个用户同时登录 2.添加同步定时器 添加 Synchronizing Timer 同步定时器,为了阻塞线程,当线程数达到指定数量,再同时释放, ...

  4. 湖湘杯2020 writeup

    这个平台中间卡的离谱,卡完过后交了flag分还掉了 Web 题目名字不重要 也算是非预期吧,赛后y1ng师傅也说了因为要多端口环境必须这样配,预期解很难 NewWebsite 后台弱口令admin a ...

  5. mac 工作区

    https://www.zhihu.com/question/20917614 http://www.bjhee.com/mission-control.html 窗口切换 https://sspai ...

  6. GoLang设计模式14 - 状态模式

    状态模式,顾名思义,是一种基于有限状态机制的设计模式.在这种设计模式中,行为是由相应的状态来决定的.接下来我们会用一个售卖机的例子来说明下状态模式.为了便于说明,我们把场景简化一下,假设有一台售卖机只 ...

  7. Dapr-状态管理

    前言: 前一篇对Dapr的服务调用方式进行了解,本篇继续对状态管理进行了解. 一.状态管理-解决的问题 在分布式应用程序中跟踪状态存在一下问题: 应用程序可能需要不同类型的数据存储. 访问和更新数据时 ...

  8. GeoServer style 配置样例

    <?xml version="1.0" encoding="UTF-8"?> <StyledLayerDescriptor version=& ...

  9. AotucCrawler 快速爬取图片

    AotucCrawler 快速爬取图片 今天介绍一款自动化爬取图片项目. GitHub: https://github.com/YoongiKim/AutoCrawler Google, Naver ...

  10. 面渣逆袭:HashMap追魂二十三问

    大家好,我是老三. HashMap作为我们熟悉的一种集合,可以说是面试必考题.简单的使用,再到原理.数据结构,还可以延伸到并发,可以说,就一个HashMap,能聊半个小时. 1.能说一下HashMap ...