前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android触摸事件传递(下)

Android触摸事件传递(下)

作者头像
三好码农
发布2018-09-11 10:55:58
1K0
发布2018-09-11 10:55:58
举报
文章被收录于专栏:三好码农的三亩自留地

  上一篇中,我说明了Android中Activity和View触摸事件的传递流程,现在我们来继续学习MotionEvent在View的容器ViewGroup中的传递过程。

  首先,ViewGroup继承于View,我们在开发中经常使用的LinearLayout,RelativeLayout,FrameLayout等都继承于ViewGroup,而Button,TextView,ImageView等都继承于View,ViewGroup对View最基本的扩展的功能就是可以添加子View。

  ViewGroup触摸事件的传递,我们要先了解onInterceptTouchEvent()方法,这个方法默认返回false,表示ViewGroup是否拦截触摸事件,即如果返回true,拦截触摸事件,则不会将任何触摸事件ev向下传递给它的子View,换一句话说,这个时候,ViewGroup就变成了我们上一篇说的View,完全走View的触摸事件传递流程,同样的我们来写代码验证。

  我们自定义一个EventRelativeLayout 继承于RelativeLayout,重写onInterceptTouchEvent方法,返回true, 重写onTouchEvent方法,返回false,然后将我们Activity的根布局改成EventRelativeLayout,然后在onCreate中给它添加onTouchListener,

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

  可以看到,我们的button没有接收到触摸事件,现在将onInterceptTouchEvent返回值改为false,再次运行App,点击按钮,查看打印日志,

   很明显,我们的按钮的触摸事件和它的父容器的触摸事件,都触发了,这是因为,我们EventBtn的onTouchListener方法和onTouchEvent方法都返回false,没有消费触摸事件,事件会向上继续传递。那么如果ViewGroup不拦截触摸事件,事件在它的子Views中又是如何传递的呢?

   触摸事件ev会按照子View加入ViewGroup先后顺序相反的顺序,依次有机会去消费此触摸事件ev,即最后加入的最先有机会消费此触摸事件,当然,它消费的前提是,触摸点的坐标在这个子View的frame范围之内,其实只需要判断触摸事件的Point是否在子控件的Rect范围之内。我们同样写代码验证。

   重写EventBtn类,如下,

  修改onCreate中的代码

    修改main布局文件

    修改布局文件,让三个按钮完全重合,加入的顺序,分别是btn1,btn2,btn3,如果按照我们的结论,触摸事件的传递顺序应该是btn3->btn2->btn1->ViewGroup->Activity,我们运行App,点击按钮,查看打印日志,

    我们可以看到,日志 打印的顺序呢,跟我们的结论一致,也就验证了我们的结论。但是我们仔细想来,好像还有点问题,就是我们一个按钮点击的动作,至少应该包含了ACTION_DOWN,ACTION_UP,二个触摸事件,但是我们打印的日志,显然只是一个触摸事件,那这是为什么呢?

    为了搞清楚上面的问题,我们继续来到View的dispatchTouchEvent方法中,我们看到下面的一段代码

    我们也很好读懂,如果事件是ACTION_UP或者ACTION_CANCEL,表示触摸结束,但是还有第三种是 如果触摸事件是ACTION_DOWN 并且result==false,同样停止嵌套的触摸事件传递,即后面的ACTION_MOVE,ACTION_UP都不会触发,因为在我们上面的例子中,没有消费触摸事件,返回的都是false,所以只触发了ACTION_DOWN事件。同样,我们可以利用代码来验证我们上面的结论,我们打开EventBtn类中dispatchTouchEvent方法中的日志打印代码,同时我们将btn3的onTouchListener方法返回true,消费掉触摸事件,然后运行App,点击按钮,查看日志。

    我们看到,这里一次按钮点击触发了4个事件,分别是ACTION_DOWN,ACTION_MOVE,ACTION_MOVE,ACTION_UP,同时所有事件全部被btn3消费掉了,这就验证了我们上面的结论,因为此时我们让btn3消费了ACTION_DOWN事件,所以后续触摸事件得以继续触发。通过上面的知识,如果我们不希望响应触摸事件,可以给ACTION_DOWN触摸事件,返回false,或者如果我们希望提前结束一个触摸事件周期,可以给targetView 发送 ACTION_CANCEL事件,如下:

    关于Android中ViewGroup的触摸事件传递就介绍到这里,难免很多地方有错误纰漏,但是我能够坚持把这些写出来,我觉得我已经有一点小小的提高了,很开心~~

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2015.04.08 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档