本文主要针对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. SimpleNVR流媒体服务系统录像功能解析

    录像的回放与观看是许多人在使用视频监控时必不可少的需求.人不可能每时每刻都观看视频,而录像能对摄像机的视频信息进行存储,方便用户的后期回放查看,因此,SimpleNVR的录像功能应运而生.       ...

  2. codeql初探

    CodeQL初探 环境搭建 基于Windows 基于Mac 下载codeql https://github.com/github/codeql-cli-binaries/releases/latest ...

  3. scrapy获取当当网多页的获取

    结合上节,网多页的获取只需要修改 dang.py import scrapy from scrapy_dangdang.items import ScrapyDangdang095Item class ...

  4. python实现拉普拉斯图像金字塔

    一,定义 二,代码: 要求:拉普拉斯金字塔时,图像大小必须是2的n次方*2的n次方,不然会报错 1 # -*- coding=GBK -*- 2 import cv2 as cv 3 4 5 #高斯金 ...

  5. 关于JAVA中顺序IO的基本操作

    关于JAVA中顺序IO的基本操作 写在前面 最近研究一下JAVA中的顺序IO,在网络上找了一会儿,发现少有详细的介绍,顾此在此处说说顺序IO,才学疏浅,如有不对,望赐教. 什么是顺序IO 事实上JAV ...

  6. [gym102538H]Horrible Cycles

    将右侧$n$个点逆序排列,并将左侧的第$i$个点插入到右侧的$a_{i}$之前(左侧的点顺序任意) 换言之,一个左侧的点恰与(排列中)其之后所有右侧的点有边 对于一个简单环,仅保留(排列中)前$i$个 ...

  7. [atARC103F]Distance Sums

    给定$n$个数$d_{i}$,构造一棵$n$个点的树使得$\forall 1\le i\le n,\sum_{j=1}^{n}dist(i,j)=d_{i}$ 其中$dist(i,j)$表示$i$到$ ...

  8. [bzoj1677]求和

    dp,用f[i]表示i划分的方案,直接枚举最后一个数是错误的,因为会导致c重复计数,然后正解十分神奇--当i为奇数,那么分解中一定有1,因此f[i]=f[i-1]当i为偶数若有1,同样转移到f[i-1 ...

  9. 面试官又整新活,居然问我for循环用i++和++i哪个效率高?

    原创:微信公众号 码农参上,欢迎分享,转载请保留出处. 前几天,一个小伙伴告诉我,他在面试的时候被面试官问了这么一个问题: 在for循环中,到底应该用 i++ 还是 ++i ? 听到这,我感觉这面试官 ...

  10. html+css第九篇

    热区: <img src="img/login.gif" alt="" border="0" usemap="#Map&qu ...