view的事件分发机制

1、点击事件的传递规则

在介绍事件传递规则之前,我们要知道的是我们所要讲的就是motionevent,即点击事件。当点击事件发生之后,系统会吧事件传递给view,而这个传递过程就是事件的分发过程,点击事件的分发过程有三个很重要的方法来完成:dispatchTouchevent,oninterceptTouchEvent,onTouchEvent。下面我们来介绍此方法。

      public boolean dispatchTouchEvent(motionevent  ev)     用来做事件的分发,如果事件能够传递给view,此方法就一定会被触发,返回结果受当前view的ontouchevent和下级view的dispatchTouchEvent方法的影响,表示是否消耗当前事件。


public   boolean  oninterceptTouchEvent (MotionEvent event)          在dispatchTouchEvent方法中调用,用来处理点击事件,返回结果表示是否消耗当前事件,如果不消耗,则在同一个事件系列中,当前view无法再接到事件。


以上方法的关系如下所示:
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
boolean consume = false;
if (onInterceptTouchEvent(event)) {
consume = onTouchEvent(event);
}else {
consume=super.dispatchTouchEvent(event);
}
return consume;
}

上述代码已经将三者的关系表现的很清晰了,通过上面的代码,我们大致能够了解点击事件的传递规则。对于一个根viewgroup来说,点击事件发生后首先会传递给他,这时它的dispatchTouchEvent方法会被调用。如果这个viewgroup的oninterceptTouchEvent 返回true就表示他要拦截当前事件,接着事件就交给viewgroup处理,即他的ontouchevent方法会被调用。如果viewgroup的oninterceptTouchEvent 返回false,就表示他不拦截当前事件,这时当前事件就会继续传给他的子元素,子元素继续执行dispatchTouchevent,如此反复,直到事件被消耗。

如果一个view需要处理事件时,如果它设置了ontouchlistener 。那么ontouchlistener中的ontouch方法将会被回调,这时事件如何处理还要看ontouch的返回值,如果返回false,则当前view的ontouchevent的方法将会被调用,如果返回true,那么当前view的ontouchevent的方法将不会被调用。由此可见view的ontouchlistener比ontouchevent的优先级高。在ontouchevent方法中,如果当前设置的有onclicklistener,那么他的onclick方法会被调用。可以看出来我们平时使用的onclicklistener其优先级最低,处于事件处理的尾端。


当一个点击事件发生后,他的处理顺序如下所示activity>window>view。以一个view的ontouchevent方法返回false,那么他的父容器ontouchevent会被调用,以此类推,如果当前view都不处理事件,全部返回,那么事件将会交给activity的ontouchevent来处理。


关于事件处理机制,我总结了如下的几个点:

(1) 同一个事件处理序列是指从手指触摸手机频幕那一节开始,到手指离开频幕那一刻结束,在这个过程所产生的一序列事件,这个事件序列以down事件开始,其间又不确定的move事件,最终以up事件结束。

(2) 正常情况下,一个事件序列只能被一个view所拦截和消耗,因为一旦一个view拦截了一个事件,那么同一个事件序列内的所有事件都会交给他来处理。因此同一个事件序列中的事件不能分由两个事件来处理,但是通过特殊手段可以做到,在ontouchevent中强行传递给其他的view进行处理。

(3) 某个view一旦决定拦截,那么这一个事件序列都只能交给他来处理,那么它的oninterceptTouchEvent 方法将不会被调用。也就是说当view决定拦截事件的时候,那么事件内的其他事件将会直接把所有的事件交给他来处理,不会再询问他处不处理。

(4) 如果一个view一旦开始消耗事件,如果它不消耗actiondown事件(ontouchevent返回了false),那么同一事件序列中的其他事件将不会再交给他来处理。并且事件将重新交由他的父元素来处理,调用父view的ontouchevent。

(5)  如果view不消耗除ACTION——DOWN以外的其他事件,那么这个点击事件将会消失,此时父元素的ontouchevent方法不会被调用。并且当前view可以持续收到后续事件,最终这些事件将会交给activity来处理。

(6) viewgroup默认不拦截任何事件。Android源码中viewgroup的oninterceptTouchEvent 方法默认返回false。

(7)view没有oninterceptTouchEvent 方法,一旦有事件传递给他,那么他的ontouchevent方法就一定会被调用。

(8) view的ontouchevent方法默认都会消耗除事件(返回true),除非他不可点击(clickable和longclickable同时为false),view的longclickable默认都为false,clickablie属性要分情况,比如button的clickable默认都为true,而textview的clickable默认都为false。

(9)view的enable不应ontouchevent的返回值。哪怕一个view为disable,只要它的clickable或者longclickable一个为true,那么他的返回值就为true。

(10)onclick会发生的前提是当前view是可点击的,并且收到了down和up的点击事件。

(11) 事件传递过程是由外向内的,即事件总是先传递给父元素,再由父元素传递给子元素。通过requestdisallowintercepttouchevent 可以在子元素中干预父元素的事件分发过程,但是action——down除外。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值