点击事件的触发流程好比去小区送快递,还不知道是谁的快递。 例子对照: 楼(ViewGroup)、进楼(ViewGroup.dispatchTouchEvent)、楼下门岗拦截(ViewGroup.onInterceptTouchEvent)、 住户房间(View)、进住户房间(View.dispatchTouchEvent)、询问用户收不收快递(View.onTouchEvent)、询问大楼管理收不收快递(ViewGroup.onTouchEvent) 首先,你是知道收件人在哪个小区的,总不可能全国去找吧 (触发事件的只有触摸点上的View,其它位置的View不响应触摸事件) 进了小区,第一次找人时你不知道在哪栋楼哪一户,只好每栋楼挨家挨户去问 (触摸的点上,所有叠着的View/ViewGroup从上层到下层遍历一遍) 当然,你总不能跨过“楼”直接问“住户” (触摸的点上,View会直接触发事件,而在ViewGroup里的View不会直接触发,而是由ViewGroup触发) 开始找人了,每遇到一栋楼肯定是先进楼 (ViewGroup.dispatchTouchEvent) 每栋楼都有门岗,他可能会拦住你,不让上楼 (ViewGroup.onInterceptTouchEvent返回true = 拦截) 若门岗没拦你,你在上楼后每遇到住户房间都要进去问 (View.dispatchTouchEvent) 询问用户收不收快递 (View.onTouchEvent) 如果用户收,你就记住了这是哪栋楼哪一户 (onTouchEvent返回true = View表示要处理触摸事件) 下次送快递时直接走向那栋楼爬到那一层就行 (不再遍历叠在一起的View,而是直接触发目标View/ViewGroup) 别误会,你只是省去了“找”的工夫,楼还是要进的 (父级的dispatchTouchEvent仍会调用,只是不会在遍历重叠的View了) 上楼时门岗照样能拦你 (ViewGroup.onInterceptTouchEvent仍然触发,可以拦截) 除非门岗收到不要管的命令 (ViewGroup.requestDisallowInterceptTouchEvent禁止拦截事件) 那样你就可以直接进楼找住户了 (ViewGroup.onInterceptTouchEvent不再触发) 如果你点背,被门岗拦住了,你就没法上楼 (ViewGroup.onInterceptTouchEvent) 只能问问这栋楼是不是收快递的 (ViewGroup.onTouchEvent) 不要惊讶,快递的收件者未必是住户,也有可能是大楼 (View、ViewGroup 都有 onTouchEvent) 你成功上楼时,如果整栋楼的住户都不收件,出楼前你也是要问大楼收不收件的 (ViewGroup遍历子View都不处理触摸后会调自己的onTouchEvent) 快递送多了总会遇到一些奇葩 比如某个收快递的住户收着收着就不收了 (处理触摸事件链的View的onTouchEvent返回了false) 遇到这种住户不要理会他,只要收了第一份快递,那么之后的快递就都要收下去,这是约定好的,继续把快递塞给他就行了。 (一旦View决定接受事件(onTouch返回true),后续onTouch返回false 也不会影响事件的分发路径) 有时候呢,某个快递送着送着,门岗就突然不让上楼了 (onInterceptTouchEvent在事件链中改为true) 这就真的没办法了,只好问问大楼收不收快递 (ViewGroup.onTouchEvent开始触发) 关于这种情况有个有趣的事情,就是当门岗第一次拦截的时候 (onInterceptTouchEvent第一次改为true) 往往都会被直接撞开,好像没有被注意到似得,这次的快递依然能送达 (onInterceptTouchEvent第一次改为true时 view.onTouchEvent依然调用) 第二次时才会注意到被拦住了,才不上去
View 触摸事件分发例子
最新推荐文章于 2024-03-20 21:23:30 发布