Android触摸事件传递(上)

    前言:智能手机早已成为我们今天身边必不可少的手持设备,iOS和Android也是目前主流的二大移动操作系统,当然也有越来越多的开发者加入到移动开发的工作中来。我也是一名普通的Android码农,目前也在学习iOS开发中,有一些成长道路上的一些经验和教训,很早就想动手记录下来,再三下决心,终鼓起勇气,敲起键盘,有了下文,初次行文,文笔未免羞涩,大神轻点喷~

    我们都知道,触摸事件对我们移动App来说至关重要,人机交互从我们手指的各种触摸手势开始,手机屏幕检测到我们的触摸事件,手机操作系统会将这些触摸事件通过回调框架提供的定义好的接口,让我们App可以接收到这些触摸事件,从而开展我们自己的业务逻辑。在Android中,系统将触摸事件包装成MotionEvent对象,同时MotionEvent类内部定义了ACTION_DOWN, ACTION_UP, ACTION_MOVE,ACTION_CANCEL等常量来表示对应触摸事件,根据这些常量的名称,我们很好理解它们对应的含义。下面,我们先提出我们的结论,然后我们一步步去验证它们。

    1.对于我们的App来说,触摸事件传递的起点从Activity的dispathTouchEvent()回调方法开始。

    我们上代码验证,我们先写一个最简单的Activity,

很简单的布局文件

很简单的按钮点击

     此时我们运行程序,点击按钮,控制台会打印 “btn clicked!” 日志,一切正常。

此时我们重写Activity的dispatchTouchEvent方法,

    再次运行程序,点击按钮,没有打印日志,按钮也没有任何触摸响应。说明触摸事件此时被屏蔽了,为了弄清楚到底怎么回事,就要去看看Activity的 dispatchTouchEvent方法的源码。

     这里分三步,第一步,如果是触摸开始类型ACTION_DOWN事件,会回调onUserInteraction()方法,所以在项目中可以考虑将一些需要用户开始触摸时就执行的代码放到此方法中;第二步,将触摸事件ev传递给Activity窗口绑定的根布局rootView,如果rootView也有子布局,会一级一级传递,具体过程我们下面会具体说明。所以如果所有布局的都没有消费此触摸事件ev,就会执行第三步 ,调用Activity的onTouchEvent()方法,否则此触摸事件ev在App层传递结束。

    上面我们讲到Activity会将触摸事件ev传递给根布局rootView,rootView有二种类型,View和ViewGroup。

     2.先说View,View触摸事件的开始还是dispatchTouchEvent(), 然后View会先将ev传递给TouchListener消费,如果TouchListener没有消费,就将ev传递给onTouchEvent,如果onTouchEvent没有消费,就会向上传递给它的父容器或者Activity,

     还是上代码,我们先验证dispatchTouchEvent,我们先自定义一个button,

    此时,我们运行程序,按下按钮,不要松开,滑动鼠标(我用的模拟器),真机此处换成手- ,-,然后松开按钮,查看控制台打印日志:

    也非常好理解,我们查看MotionEvent源代码,ACTION_DONW = 0, ACTION_UP=1, ACTION_MOVE=2, 打印的日志与我们手指的触摸操作完全一致,先是触发了ACTION_DOWN事件,然后是几个ACTION_MOVE事件,最后是ACTION_UP事件。

    接下来,我们给EventBtn添加onTouchListener,并返回true

   运行App,查看打印的日志,

    我们看到,没有打印 btn clicked日志,验证了我们说明的View事件传递的第一部分,触摸事件ev,优先被onTouchListener消费掉了,后面的onTouchEvent和onClickListener都不会再收到点击的触摸事件了。下面我们将onTouchListener的返回值改为false,并重写EventBtn onTouchEvent方法,并返回true。

   运行App,点击按钮,查看打印的日志,

   这也验证了我们关于View触摸事件传递的第二部分,触摸事件ev优先被onTouchListener消费,然后再让传递给onTouchEvent消费。

   现在我们通过代码验证我们关于View触摸事件传递机制的结论,为了进一步佐证我们的结论,我们还得去查看View的框架源码,我们打开View的源码,找到dispatchTouchEvent方法,

    看到源码,很一目了然,框架先调用onTouchListener,如果事件没有被消费掉,再调用onTouchEvent,最后result表示此触摸事件是否被消费,作为返回值。

    下一篇日记我们去学习关于ViewGroup的 消息传递,具体请听下回分解~~

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏非著名程序员

拖拽,自由组合,让你的开发更加简单,用户更方便

今天给大家推荐一个自由拖拽,自由组合的控件,这个控件是我自定义写的。通过它,我们可以自由拖拽,自由组合实现一个界面,满足一个用户自由组合界面的需求。这里不是通过...

2376
来自专栏IMWeb前端团队

React-Native简介

React-Native 基于目前React来开发IOS原生应用,Android版本将在年底推出。 为什么需要React-Native 目前主流的应用大体分成三...

32910
来自专栏腾讯NEXT学位

【干货】解剖小程序的 setData

双线程的渲染机制、通信机制,setData 的出现、工作原理、使用建议等,应该要怎么去理解呢?

8332
来自专栏韩东吉的Unity杂货铺

零基础入门 4: 窗口介绍(完)

上一篇将Unity里几个比较重要的窗口先进行了讲解,以及如何自定义窗口布局,不知道大家都消化的怎么样,今天这篇窗口介绍,将把剩余window的窗口一一进行介绍。

1561
来自专栏james大数据架构

Android一些关于分辨率和布局的设置

1、Android手机屏幕大小不一,有480x320, 640x360, 800x480.怎样才能让App自动适应不同的屏幕呢? drawable- hdpi、...

2079
来自专栏DeveWork

CSS 命名之Dialog, Modal, Popup, Popover, Lightbox 等的区别

写 CSS 时候经常遇到要为弹窗浮层这些进行 class 命名的情况,之前对于Dialog, Modal, Popup, Flash,Tooltip等这类命名一...

3476
来自专栏Sorrower的专栏

界面无小事(八):RecyclerView增删item

1463
来自专栏九彩拼盘的叨叨叨

HTML相关的面试题

在浏览器中有三种渲染模式: 怪癖模式(quirks mode),准标准模式(almost standards mode)和标准模式(standards mode...

973
来自专栏腾讯Bugly的专栏

《Pluto - iOS 上一个高性能的排版渲染引擎》

| 导语 Pluto 是 iOS 上的一个排版渲染引擎,通过 JSON/JS 文件可以很方便地描述界面元素,开发效率很高,并且在流畅度,内存等方便有保证 Qzo...

3357
来自专栏代码GG之家

android recent key长按事件弹起触发最近列表故障分析

问题描述 [Dialer]it will appear different behaviors after long press the menu to ex...

2365

扫码关注云+社区

领取腾讯云代金券