文档章节

View 事件传递机制

CRAZY261
 CRAZY261
发布于 2015/07/26 13:28
字数 1386
阅读 4039
收藏 132

View事件传递 touch事件分发

学习Android一年有余,今天开始以自己的理解去介绍一下Android开发常用到的基础技术。第一个介绍的是View 的事件传递机制,建议首先去看一下[codeKK中关于View事件传递介绍的文章][1],我这里只是对这个的补充以及自己理解。有不正确的地方欢迎拍砖☺。

第一部分:知识储备

  1. 在Android中所有的TouchEvent事件都封装在MotionEvent对象中,而TouchEvent事件主要包括Touch的位置,时间,历史记录,滑动等等。
  2. 常见MotionEvent的类型包括:ACTION_DOWN,ACTION_MOVE,ACTION_CANCEL,ACTION_UP,ACTION_SCROLL等等。
  3. 我们关心的对事件的处理实质上就是dispatchTouchEvent,onTouchEvent,onInterceptTouchEvent这三个函数,分别代表事件传递,事件消费和事件拦截的意思,这三个函数都是boolean类型的,如果返回值为true代表该事件被消耗。

(注明:以上的内容是从codeKK文章中部分摘取的)

第二部分:实战演练

以我的理解,要掌握整个事件的传递过程,必须得理清楚那三个事件处理函数,最好是自己写写代码验证一下。 以下我根据事件的消耗分四个部分:不拦截不消费,不拦截消费,拦截不消费,拦截消费。为了更好的理解,假设布局层次如下:

UI Automator

这个是在UI Automator中的截图,布局很简单,最外层为一个LinearLayout,然后嵌套了两个LinearLayout。在这个里为了方便我简称为从最外到里分别为L0,L1,L2。其预览图如下:

预览图

布局文件如下:

<?xml version="1.0" encoding="utf-8"?>
<com.example.TouchEventDemo.MyLinearLayout0
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:id="@+id/L0"
        android:background="@android:color/white"
        >
    <com.example.TouchEventDemo.MyLinearLayout1
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/L1"
            android:layout_margin="20dp"
            android:background="@android:color/holo_blue_dark"
            >
        <com.example.TouchEventDemo.MyLinearLayout2
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:id="@+id/L2"
                android:background="@android:color/holo_red_light"
                android:layout_margin="20dp"
                android:orientation="horizontal"
                />
    </com.example.TouchEventDemo.MyLinearLayout1>
</com.example.TouchEventDemo.MyLinearLayout0>

这里为了更好的看清楚事件的传递,我们需要自定义三个LinearLayout,并重写三个事件函数,dispatchTouchEvent,onTouchEvent,onInterceptTouchEvent

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        Log.i(TAG, "MyLinearLayout0------------dispatchTouchEvent");
        return super.dispatchTouchEvent(ev);
    }
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.i(TAG, "MyLinearLayout0------------onTouchEvent");
        return super.onTouchEvent(event);
    }
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        Log.i(TAG, "MyLinearLayout0------------onInterceptTouchEvent");
        return super.onInterceptTouchEvent(ev);
    }

好了,前期准备工作已经完成,我们开始验证: ####1.不拦截不消费: 即所有的onTouchEvent,onInterceptTouchEvent函数返回为fasle。预期的流程应该是:

输入图片说明

当我们点击L2即红色区域程序运行的结果是:

输入图片说明

可以看到和我们预期的一模一样。 ####2.不拦截消费: 这里假定L1对事件不拦截消费,即L1.onInterceptTouchEvent位false,L1.onTouchEvent返回为true,说明L1对消费了事件,且没有拦截事件。同样我们的预期流程应该有两种情况: 第一种:L2消费掉事件,即L2.onTouchEvent返回为true,其流程应该是:

输入图片说明

当我们点击L2即红色区域程序运行的结果是:

输入图片说明

第二种:L2没有消费掉事件,即L2.onTouchEvent返回为fasle,其流程应该是:

输入图片说明

当我们点击L2即红色区域程序运行的结果是:

输入图片说明

到这里前两种情况基本介绍完了,总结下,在这里最重要的一点要记住,如果子VIEW没有消费掉ACTION_DOWN的事件,则后续的UP/MOVE事件将不会到来。

####3.拦截不消费: 这里假定的对象还是L1,即L1对事件拦截但不消费,即L1.onInterceptTouchEvent位true,L1.onTouchEvent返回为false。从字面上可以L1拦截了事件,则L2是不会在接受到任何事件的。预期的流程应该是:

输入图片说明

当我们点击L2即红色区域程序运行的结果是:

输入图片说明

可以看到和我们流程图是一样的。 ####4.拦截消费: 这里假定的对还是L1,即L1对事件拦截且消费,即L1.onInterceptTouchEvent位true,L1.onTouchEvent返回为true。预期的流程应该是:

输入图片说明

当我们点击L2即红色区域程序运行的结果是:

输入图片说明

运行结果和流程图一样 ##第三部分:总结 以上就是就是view事件传递的流程,当然还没有包括点击,长按等事件。下面对全文做个总结: (1) 事件从 Activity.dispatchTouchEvent()开始传递,只要没有被停止或拦截,从最上层的 View(ViewGroup)开始一直往下(子 View)传递。子 View 可以通过 onTouchEvent()对事件进行处理。

(2) 事件由父 View(ViewGroup)传递给子 View,ViewGroup 可以通过 onInterceptTouchEvent()对事件做拦截,停止其往下传递。

(3) 如果事件从上往下传递过程中一直没有被停止,且最底层子 View 没有消费事件,事件会反向往上传递,这时父 View(ViewGroup)可以进行消费,如果还是没有被消费的话,最后会到 Activity 的 onTouchEvent()函数。

(4) 如果 View 没有对 ACTION_DOWN 进行消费,之后的其他事件不会传递过来。

(5) OnTouchListener 优先于 onTouchEvent()对事件进行消费。

源代码:链接:http://pan.baidu.com/s/1sjsUmsP 密码:v6lp

© 著作权归作者所有

CRAZY261
粉丝 4
博文 8
码字总数 8442
作品 0
成都
高级程序员
私信 提问
加载中

评论(7)

木有橙子
手机客户端看的,图片字太小了
菜根
菜根
13不错,学习了
whinc
whinc
不错,不过感觉分析源码可能更清楚
壹地鸡毛
壹地鸡毛
赞一个,android事件处理的主要逻辑在View和ViewGroup两个类的dispatchTouchEvent方法里。这两个dispatchTouchEvent方法看一下就了解大概了
开源中国阅卷组组长
开源中国阅卷组组长
不错,马克
CRAZY261
CRAZY261 博主

引用来自“Kooosy”的评论

大兄弟, 你这图是用的什么工具画的啊.
用的Visio
Kooosy
Kooosy
大兄弟, 你这图是用的什么工具画的啊.
Android6.0源码解读之Activity点击事件分发机制

本篇博文是Android点击事件分发机制系列博文的第四篇,主要是从解读Activity类的源码入手,根据源码理清Activity点击事件分发原理,并掌握Activity点击事件分法机制。特别声明的是,本源码解...

mynameishuangshuai
2016/10/23
0
0
Android6.0触摸事件分发机制解读

本篇博文是Android触摸事件分发机制系列博文的第一篇,带领大家从全局掌握Android触摸事件分发机制。特别声明的是,本源码解读是基于最新的Android6.0版本。 (一)Android6.0源码解读之Vie...

mynameishuangshuai
2016/10/24
0
0
Android源码分析-点击事件派发机制

转载请注明出处:http://blog.csdn.net/singwhatiwanna/article/details/17339857 概述 一直想写篇关于Android事件派发机制的文章,却一直没写,这两天刚好是周末,有时间了,想想写一篇吧,...

长平狐
2013/12/25
1K
0
关于CoordinatorLayout AppBarLayout原理的一些分析

这几天学了一些CoordinatorLayout、AppBarLayout配合使用的一些方法,之前还写了一篇CoordinatorLayout Behavior一些笔记,通过这几天对源码的阅读,现在对CoordinatorLayout、AppBarLayout这...

HumorousMan
2017/06/11
0
0
Android 机制篇 - 事件分发机制超详解(🔥🔥🔥🔥🔥🔥🔥🔥)

Android 虽然不是四大组件,但其并不比四大组件的地位低(涉及面的广度和深入甚至比四大组件还复杂🔥)。而View的核心知识点“事件分发机制”则是不少刚入门同学的拦路虎(1、项目中处处遇...

Pepsimaxin
2018/07/12
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Java常见异常处理

异常是Java程序中经常遇到的问题,一个异常就是一个Bug,就要花很多时间来定位异常。 Java异常 (1)Throwable是Java异常的顶级类,所有的异常都继承于这个类。 (2)Error,Exception是异常...

daxiongdi
30分钟前
4
0
Validator 常用注解

说明 Validator主要是校验用户提交的数据的合理性的,比如是否为空了,密码长度是否大于6位,是否是纯数字的,等等。那么在spring boot怎么使用这么强大的校验框架呢。 常用 [@null](https:...

五彩的颜色
39分钟前
3
0
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。

#1 先把入栈顺序的第一数据入栈, #2 if 入栈的数据==等于出栈的数据,就循环一次看是否新建的栈的数据是否出栈 #3 返回新建的栈是否为空,就是要的结果 public class Solution { public boo...

winkwink
45分钟前
4
0
《JAVA核心知识》学习笔记 (19. 数据库)

19.1.1. 存储引擎 19.1.1.1. 概念 数据库存储引擎是数据库底层软件组织,数据库管理系统(DBMS)使用数据引擎进行创建、查询、 更新和删除数据。不同的存储引擎提供不同的存储机制、索引技巧...

Shingfi
51分钟前
4
0
三分钟手操自己的yum源

本文章原创首发公众号:编程三分钟 上次就想手操yum源了,考虑到有的朋友没接触过,直接写成了yum源的科普,活活憋了我一个星期,现在我们快快开始。 什么情况下我们需要搭建一个仓库呢? 记...

编程三分钟
55分钟前
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部