Android知识梳理:点击事件分发机制

前言

Android的点击事件分发一直是面试的高频问题,也涉及应用项目的多个地方,今天特此总结梳理一下这部分的知识

大纲

1.简介

2.结论

3.论证

4.其他问题

正文

1.简介

角色:Activity、ViewGroup、View

相关方法:dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent

事件:DOWN、MOVE、UP、CANCEL...(在此主要讨论DOWN)

2.结论

真想用简短的一句话总结这么多东西的机制,但是还是有难度的,来个实际的应用题吧。

问:有个ActivityA、里面有个ViewGroupA、里面有个ButtonA,现在手指点击一下ButtonA,这个touch事件是怎么分发处理的?

答1:若ButtonA未注册onClick事件(未setOnClick):

DOWN事件流程:

ActivityA.dispatchTouchEvent() -> ViewGroupA.dispatchTouchEvent() -> ViewGroupA.onInterceptTouchEvent(默认不拦截)

-> ButtonA.dispatchTouchEvent() -> ButtonA.onTouchEvent()(不消费返回flase) 分发到view不消费开始上传

-> ViewGroupA.onTouchEvent() -> ActivityA.onTouchEvent()

点击事件未被任何view接受,因此后续的MOVE、UP事件也不会下发

MOVE或UP事件流程:

ActivityA.dispatchTouchEvent() -> ActivityA.onTouchEvent()

 

答2:若Button未注册onClick事件(设置setOnClick):

DOWN事件流程:

ActivityA.dispatchTouchEvent() -> ViewGroupA.dispatchTouchEvent() -> ViewGroupA.onInterceptTouchEvent(默认不拦截)

-> ButtonA.dispatchTouchEvent() -> ButtonA.onTouchEvent()(消费返回true)

有view消费,余下事件同样下发至此view

MOVE或UP事件流程:

ActivityA.dispatchTouchEvent() -> ViewGroupA.dispatchTouchEvent() -> ViewGroupA.onInterceptTouchEvent(默认不拦截)

-> ButtonA.dispatchTouchEvent() -> ButtonA.onTouchEvent() -> ButtonA.onClickListener

然后,当情况2时,如果在之前DOWN事件ViewGroupA中未拦截,在MOVE事件拦截了一次,即复写ViewGroupA.onInterceptTouchEvent返回true,那么ButtonA会收到一个CANCEL事件

3.论证

实际log论证下上面的情况,代码就不贴了,log标识的很清楚

答1.未注册btn setOnClick(view不消费)
dispatchTouchEvent()
TouchTestActivity -> TestLinearLayout -> TestButton

onTouchEvent
TouchTestActivity <- TestLinearLayout <- TestButton

 答2.注册btn setOnClick(View消费)

 4.其他问题

1.Activity和View只有dispatchTouchEvent()和onTouchEvent()两种方法,ViewGroup有dispatchTouchEvent()、onTouchEvent()和onInterceptTouchEvent()三种方法

2.当Acitivty接收到Touch事件时,将遍历子View进行Down事件的分发。ViewGroup的遍历可以看成是递归的。分发的目的是为了找到真正要处理本次完整触摸事件的View,这个View会在onTouchuEvent结果返回true。

3.当某个子View返回true时,会中止Down事件的分发,同时在ViewGroup中记录该子View。接下去的Move和Up事件将由该子View直接进行处理。由于子View是保存在ViewGroup中的,多层ViewGroup的节点结构时,上级ViewGroup保存的会是真实处理事件的View所在的ViewGroup对象

4.当ViewGroup中所有子View都不捕获Down事件时,将触发ViewGroup自身的onTouch事件。触发的方式是调用super.dispatchTouchEvent函数,即父类View的dispatchTouchEvent方法。在所有子View都不处理的情况下,触发Acitivity的onTouchEvent方法。

5.onInterceptTouchEvent有两个作用:拦截Down事件的分发;中止Up和Move事件向目标View传递,使得目标View所在的ViewGroup捕获Up和Move事件。

6.在一次手势过程中,如果前面的事件父View没有拦截,这次事件父View拦截了,那么子View会马上收到一个ACTION_CANCEL事件

总结

以上就是对于点击事件分发机制的大致总结,详细还需根据源码做进一步更深层次的理解,并且结合自定义View演练一下已达到活学活用的效果

参考

https://www.jianshu.com/p/38015afcdb58

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值