【Android】の基础——View事件分发

事件分发机制

这个系列准备分享一些自己有独特见解的知识点。

从一个故事讲起

用户点击屏幕会触发一个MotionEvent,它就是我们要进行分发的事件。事件分发的最终目标是希望有一个View能够给他返回一个True,即进行了处理(消耗该事件)。在这里,我们把事件分发的过程,比喻成一个大学生event(MotionEvent)想要在大学(Activity)中通过加入社团(ViewGroup),来寻找女盆友(View),从而找到真爱(True)的故事,我们将会以上帝视角来监视这个过程。

这里写图片描述

这里写图片描述
部长开会讨论的怎样分配event的过程相当于事件分发中的:
dispatchTouchEvent()

这里写图片描述
如果妹纸部长不让event进入部门里,就是不允许事件从当前ViewGroup传递到子View(或者子ViewGroup),也就是拦截了event(虽然拦截但是未必处理(未必消耗)),这个过程相当于:
onInterceptTouchEvent()

这里写图片描述
event找到了目标,目标可能是部长,可能是部员,也可能是其他的部门部长或者部员,这个目标可能是View,也可能是ViewGroup。反正在这个故事中,这个目标最终做出了回应,这个过程相当于:
onTouchEvent()

所以,事件分发的核心过程我们可以用这样一段伪代码进行表示:

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

事件在ViewGroup中进行分发,如果没有被消耗,则通过onInterceptTouchEvent()判断是否需要拦截,如果拦截则交给本ViewGroup的onTouchEvent()进行处理,如果不拦截则交给子View(或ViewGroup)继续重复dispatchTouchEvent()的过程进行分发,从外向内,以此类推。
以下:
1. 事件从Activity.dispatchTouchEvent()开始传递,只要没有被停止或拦截,从最上层的View(ViewGroup)开始一直往下(子View)传递。子View可以通过onTouchEvent()对事件进行处理。
2. 事件由父View(ViewGroup)传递给子View,ViewGroup可以通过onInterceptTouchEvent()对事件做拦截,停止其往下传递。
3. 如果事件从上往下传递过程中一直没有被停止,且最底层子View没有消费事件,事件会反向往上传递,这时父View(ViewGroup)可以进行消费,如果还是没有被消费的话,最后会到Activity的onTouchEvent()函数。
4. 如果View没有对ACTION_DOWN进行消费,之后的其他事件不会传递过来。
5. OnTouchListener优先于onTouchEvent()对事件进行消费。

此外,我们在之前的故事中特别地标注了一些“重要情节”,现在来进行解释:
这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

总结下来就是:
1. 一旦 ViewGroup决定拦截,一个事件只能由他处理并且onInterceptTouchEvent不会再调用。
2. 如果View只消耗ACTION_DOWN,事件会消失(不会被parent处理),最终Activity处理。
3. View如果不消耗ACTION_DOWN,其他事件也不处理。重新交给父元素,即调用父元素onTouchEvent。
4. viewgroup默认不拦截
5. View没有onInterceptTouchEvent
6. 除非不可点击(clickable、longClickable都为false),View的onTouchEvent()默认返回true,甚至enable都影响不了。
7. onTouchListener优先级高于onTouchEvent,如果onTouchListener返回True,onTouchEvent不执行

具体的源码今后再分析。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值