前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android 事件分发机制

Android 事件分发机制

作者头像
android_薛之涛
发布2018-10-09 12:17:45
1.4K0
发布2018-10-09 12:17:45
举报
文章被收录于专栏:Android-薛之涛Android-薛之涛

事件分发机制在android中非常常见,比如:手势滑动,自定义View,多点触控都有它的身影。事件分发的顺序是:Activity->GroupView->View,GrounpView包括五大布局,ListView和GridView等,View包括TextView,ImageView等。我们今天就来搞一下。

首先我们的手指和屏幕接触的MotionEvent对象会产生一系列事件,它有四种状态:

MotionEvent对象的四种状态:

  • MotionEvent.ACTION_DOWN:手指按下屏幕的瞬间
  • MotionEvent.ACTION_MOVE:手指在屏幕上移动
  • MotionEvent.ACTION_UP:手指离开屏幕瞬间
  • MotionEvent.ACTION_CANCEL :取消手势,一般由程序产生

事件分发所涉及的主要方法:

1.1 dispatchTouchEvent

用来进行事件分发和传递的,返回true的时候一定是自己去消费,返回false有可能是自己消费也有可能是传递给上一级的OnTouchEvent方法, super就传递给其他的view。该方法也是触摸事件第一个执行的方法。

1.2 onInterceptTouchEvent

是viewGroup特有的,用来做触摸事件拦截的,默认返回false:如果false或者super表示不拦截,事件继续向下传递。事件所经过的每一层的viewGroup都会去调用该方法来询问是否拦截。如果返回true,则代表拦截该事件,停止传递给子view,会走自己的onTouchEvent事件 事件被拦截后,子view会接收到一个cancel事件,来恢复之前的状态,结束当前事件流。

1.3 requestDisallowInterceptTouchEvent

是viewGroup专有的方法,也是事件拦截用的,和onInterceptTouchEvent类似。不过一般是在子view中来调用的。

1.4 onTouch

是触摸事件,当一个触摸事件被分发到一个view的时候。

1.5 onTouchEvent

真正用来处理触摸事件的最后调用的方法, onTouchEvent是否拦截取决于down事件。

1.6 onClick

是一个点击事件,是在onTouchEvent的up事件里面执行的,它的优先级是最低,如果在onTouchEvent或OnTouchListener的onTouch方法如果返回true,则不响应onClick方法。

onTouch,onTouchEvent和onClick的执行顺序:onTouch—>onTouchEvent—>onClick,注意:onClick直接消费掉了事件,不会再向上回溯事件了。 我们来一个表格了解一下Activity和ViewGroup和View各自拥有的方法:

类型

拥有方法

Activity

dispatchTouchEvent,onTouchEvent

GroupView

dispatchTouchEvent,onTouchEvent ,onInterceptTouchEvent,requestDisallowInterceptTouchEvent

View

dispatchTouchEvent,onTouchEvent ,onTouch,onClick

在来一张图了解一下其分发流程(自己写的,体谅一下):

image.png

一共分有三层,Activity——>ViewGroup——>View,其中ViewGroup比其他两个多了一个onInterceptTouchEvent方法,箭头代表了事件流的走向,箭头上的值表示该方法的返回值,消费框表示事件被消费掉,不会向下或者向上传递,接下来我们写代码运行一下看效果。

测试部分

1.首先先自定义一个view(TextView)和一个ViewGroup(ReleativeLayout),然后重新其dispatchTouchEvent,onTouchEvent等方法,布局关系基本是这样的:

image.png

已ViewGroup为例,部分代码是这样的:

image.png

我们先啥也不干,就正常点击一下,打印看看:

image.png

由于我们只是点击然后迅速抬起,所以没有Action_Move这个动作,所以正常的事件流程应该是这样的: 事件依次从Activity的dispatchTouchEvent——>ViewGroup的dispatchTouchEvent——>ViewGroup的onInterceptTouchEvent——>View的dispatchTouchEvent——>View的onTouchEvent——>ViewGroup的onTouchEvent——>Activity的onTouchEvent流转完成,由于没有事件没有被消费,所以事件一路传递下来,又一路回溯回去,所以最终事件就被Activity消费了(就是Activity的UP事件)。

2.我们刚才是正常的事件分发流程图,没有给View即TextView设置click事件,那我们现在给TextView设置点击事件看看,事件是怎么分发的?

image.png

可以看到如果给View设置了click事件,那么事件会最终分发给view,被view消费,这就是我们平时最常用的事件分发流程

3.其他的你们都可以在个个阶段的事件分发中,返回不同的值去测试验证,我们再说一个viewGroup的onInterceptTouchEvent()返回true和onTouchEvent也返回true看一下:

image.png

可以看到被拦截之后,后续move,up事件都交给自己处理,并且不再调用onIntercepetTouchEvent,而且事件也不再传递到子View

4.那如果我们不想让TextView的点击事件响应怎么办,按照上面的andorid事件分发流程图,方法多了,我们可以在不同的阶段进行控制,不让事件向下分发,但我们试试onTouch()这个方法,此方法默认返回false,我们现在让它返回true试试。测试结果是可以的,也就是说onTouch()方法返回true也是自己消费了,不会在向下传递到onTouchEvent()了,更不会传递到onClick()了,如图:

image.png

image.png

ACTION_CANCEL的出现时机

ACTION_CANCEL的出现场景为:手指点击屏幕停顿,让系统以为view的onTouchEvent要消费此事件的时候滑动,在onInterceptTouchEvent()中拦截,交给ViewGroup来处理此次事件,这个时候就会额外触发一个ACTION_CANCEL来传递给子view来恢复子view的状态. 那么我们怎么做呢?

  • 先让系统以为view的onTouchEvent要消费事件:在view的onTouchEvent中return true,结果如下:

image.png

此时事件是被view的onTouchEvent消费了。

  • 在viewGrounp的onInterceptTouchEvent方法中对ACTION_MOVE动作进行拦截return true,把属于view的事件给转移到ViewGroup消费,结果如下:

image.png

ACTION_CANCEL这个动作目前是被触发了,但大家有没有发现后续move没有再经过ViewGroup,明明是在ViewGroup的ACTION_MOVE中return true消费了呀? 原因是:还需要在ViewGroup的onTouchEvent返回true才行,不然viewGroup又会默认super,把ACTION_MOVE等传递给了Activity消费而不是自己消费,那我们现在改一下,运行如下:

image.png

这样才对嘛。 项目已上传github.

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

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • MotionEvent对象的四种状态:
  • 事件分发所涉及的主要方法:
    • 1.1 dispatchTouchEvent
      • 1.2 onInterceptTouchEvent
        • 1.3 requestDisallowInterceptTouchEvent
          • 1.4 onTouch
            • 1.5 onTouchEvent
              • 1.6 onClick
                • ACTION_CANCEL的出现时机
            • 测试部分
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档