View 的事件分发机制

定义:事件分发,以点击事件为例,即当一个MotionEvent产生,到系统将这个事件传递给一个具体的 View 的过程,就是分发的过程。

主要包括三个重要的方法:dispatchTouchEventonInterceptTouchonTouchEvent

fun dispatchTouchEvent(ev: MotionEvent?):Boolean:用来进行事件分发,如果事件能够传递给当前 View ,那么该方法一定会被调用,返回结果受当前 View 的 onTouchEvent 和下级 View的 dispatchTouchEvent 影响,返回是否消耗当前事件。

fun onInterceptTouch(ev:MotionEvent?):Boolean:在 dispatchTouchEvent 方法内部调用,用来判断是否拦截某个事件,(默认如果拦截,那么同一个事件序列当中,在拦截以后的事件,将不会被调用。
备注 :同一个事件序列包括 ACTION_DOWN + n 个 ACTION_MOVE + ACTION_UP

fun onTouchEvent(ev:MotionEvent?):Boolean 在 dispatchTouchEvent 方法内部调用,用来处理点击事件,如果不消耗,同一个事件序列中,当前 View 无法接收后续事件。
备注 :注意都是在同一个事件序列中,当下一次点击,有新的事件序列是,会继续被调用。

以上三个方法当结构关系如下:

public boolean dispatchTouchEvent(MotionEvent ev){
		boolean consume = false;
		if (onInterceptTouchEvent(ev)) {
			consume = onTouchEvent(ev);
		} else {
			consume = child.dispatchTouchEvent(ev);
		}
			
	return consume;
}

其中 view 的 onTouchListener 响应高于 onTouchEvent,其中 onClickListener 在 onTouchEvent 中回调,所以,如果 View 设置类onTouchListener 则不会响应 onClickListener。

在这里插入图片描述

详细图讲解:
事件分发顺序:Activity -> Window -> View
首先,Activity,如果它自己将事件消耗,就不会有后面什么事儿了。
然后,如果可以传递给 ViewGroup,则它会走上面的黑体加粗的三个 fun 方法,经过 dispatchTouchEvent 方法,如果拦截事件,则受自身的 onTouchEvent 影响,如果不拦截事件,受子元素的 dispatchTouchEvent 影响,所以,他会有左右两个出口,自身 onTouchEvent 返回 false ,则该事件会向上传递给 父元素的 onTouchEvent,最终到Activity。或者向下传递给子元素的 dispatchTouchEvent ,又开始新一轮的循环。
最终,传递给 View , 由于 View 没有 onInterceptTouchEvent ,所以它只能走 onTouchEvent ,如果不消耗,就继续向上传递,或者直接在分发的时候 return true,消耗事件。
以上就是View的事件分发的详细流程。

事件传递的结论

  1. 同一个事件序列,是指从手指接触屏幕,到离开屏幕这个过程所产生的一系列事件,即 ACTION_DOWN + n 个 ACTION_MOVE + ACTION_UP。
  2. 正常情况,一个事件序列,只能被一个View拦截且消耗。但,View 也可以在 OntouchEvent 中强行传递给别但 View 进行处理。
  3. 当 onInterceptTouchEvent 返回 true,则这个事件序列中剩余当事件都由它来处理,并且剩余当事件也不会再调用onInterceptTouch。
  4. 如果 onTouchEvent 的 ACTION_DOWN 返回 false ,则同一事件序列会交由父元素处理。
  5. 如果 onTouchEvent 只消耗 ACTION_DOWN,则同一事件序列其他事件最终会传递给Activity。
  6. ViewGroup 的 OnInterceptTouchEvent 默认返回 false。
  7. View 没有 OnInterceptTouchEvent,所以有方法传递给它,默认执行 onTouchEvent。
  8. View 的 OnTouchEvent 默认返回 true,除非是( clickable && longClickable ) == false 其中,View 的 longClickable 默认为 false,但Clickable 像 Button 默认返回 true , TextView 默认返回 false。
  9. View 的enable不影响 OnTouchEvent,因为它不影响 clickable 和 longClickable属性。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值