Android 事件分发机制(4)-常见面试题

目录

1.你了解过Android的事件分发机制吗?请大致介绍一下

2、如果父view中不拦截down事件,拦截move,up事件,在子view中设置了requestDisallowInterceptTouchEvent(true);(请求父view不拦截事件)这个标志后,子view能收到move,up事件吗?

3、如果某个view 处理事件的时候 没有消耗down事件 会有什么结果?

4.如果view 不消耗move或者up事件 会有什么结果?

5.setOnTouchListener中onTouch的返回值表示什么意思?

6. 如果view设置了onTouchListener,onClickListener,onTouchEvent,那么会先执行哪一个?

7.ViewGroup 默认拦截事件吗?

8.requestDisallowInterceptTouchEvent 可以在子元素中干扰父元素的事件分发吗?如果可以,是全部都可以干扰吗?如果不可以干扰,为什么

9.遇到过滑动冲突没,怎么解决的


1.你了解过Android的事件分发机制吗?请大致介绍一下

事件分发机制主要涉及3个方法,3个对象,3个事件

3个方法分别是

dispatchTouchEvent 返回类型是布尔类型的,表示事件是否分发,如果为false的话,则返回上一层

onInterTouchEvent   返回类型是布尔类型的,在dispatchTouchEvent内部调用,ViewGroup中调用的,表示事件是否拦截,如果拦截的话,会在ViewGroup中消费事件,执行ViewGroup的onTouchEvent方法,否则会继续分发给View

onTouchEvent 返回类型是布尔类型 dispatchTouchEvent中调用 View中默认为ture,表示消费该事件

3个对象:

Activity->ViewGroup->View

3个事件分别是:

ACTION_DOWN:返回true,说明当前View来处理事件,后续事件也要处理,事件不再向下传递;返回false,说明当前View不处理事件,后续事件直接由上一级View处理,当前View也不会再接收到后续事件
ACTION_MOVE、ACTION_UP:返回true,说明其子View已经接收了DOWN事件,这里返回true只会导致该部分事件不再继续向下传递(但也不会传递当前View的onTouchEvent处理),对于没有返回true的事件还按正常流程传递

点击事件产生后,首先会传递给Activity.dispatchTouchEvent方法中,然后会调用getWindow.superDispatchTouchEvent,然后因为window是个抽象类,PhoneWindow是唯一的实现类,所以会通过mDector.dispatchTouchEvent去调用父类的dispatchTouchEvent,然后mDector。也就是DectorView,是个FrameLayout,是个ViewGroup,所以本质上会调用ViewGroup的dispatchTouchEvent,该方法会通过onInterTouchEvent返回值来判断是否进行事件拦截,为false的话不进行拦截或者判断requestDisallowInterTouchEvent是否为ture,如果为true的话,也不进行拦截,如果不进行拦截的话,则遍历子View,依次执行dispatchTransformedTouchEvent方法,这方法会判断是否有子View,如果有的话,则执行View的dispatchTouchEvent方法,如果没有的话,就会执行ViewGroup的父类,也还是View的dispatchTouchEvent方法。

最终会执行onTouchEvent的ACTION_DOWN方法,返回true,表示事件消费完成,后续的ACTION_MOVE(可能有多个)、ACTION_UP也会照着这个流程传递下来,否则如果ACTION_DOWN返回false,则会依次向上传递到上层的onTouchEvent中,同时后续的ACTION_MOVE、ACTION_UP不会往下传递了,然后如果父View对后续的除了DOWN以外的事件进行拦截的话,那么子View只会收到一个ACTION_CANCLE消息,同时后续的事件在父View中处理了

2、如果父view中不拦截down事件,拦截move,up事件,在子view中设置了requestDisallowInterceptTouchEvent(true);(请求父view不拦截事件)这个标志后,子view能收到move,up事件吗?

根据情况来定,

(1)如果子View消费了Down事件,并且设置了requestDisallowInterceptTouchEvent(true)那么后续的move、up事件会正常传过来

(2)如果子view不消费Down事件,并且设置了requestDisallowInterceptTouchEvent(true),则只会收到Down事件,后续的move、up事件收不到

3、如果某个view 处理事件的时候 没有消耗down事件 会有什么结果?

在down事件来的时候 他的onTouchEvent返回false, 那么这个down事件 所属的事件序列 就是他后续的move 和up 都不会给他处理了,全部都给他的父view处理。

4.如果view 不消耗move或者up事件 会有什么结果?

那这个事件所属的事件序列就消失了,父view也不会处理的,最终都给activity 去处理了。

5.setOnTouchListener中onTouch的返回值表示什么意思?

返回true,表示事件被消耗掉了,onClick跟onLongClick将不再执行,返回false,可以继续传递onClick跟onLongClick还是会继续执行

6. 如果view设置了onTouchListener,onClickListener,onTouchEvent,那么会先执行哪一个?

这块由View的dispatchTouchEvent源码可知,优先执行onTouchListener.onTouch方法,然后在往下执行onTouchEvent方法中执行onClickListener

7.ViewGroup 默认拦截事件吗?

默认不拦截,由源码onInterceptTouchEvent可知,默认return false

8.requestDisallowInterceptTouchEvent 可以在子元素中干扰父元素的事件分发吗?如果可以,是全部都可以干扰吗?如果不可以干扰,为什么

正常是都可以干扰,除了ACTION_DOWN事件,因为ACTION_DOWN事件在ViewGroup的dispatchTouchEvent中刚开始会调用resetTouchState重置,所以当在判断disallowIntercept的时候始终都为false,从而对它造成不了影响,所以如果父元素对ACTION_DOWN进行拦截的话,那么后续的事件是分发不到子View的,子View只会收到ACTION_DOWN事件和ACTION_CANCLE事件

9.遇到过滑动冲突没,怎么解决的

有2种解决方法:

1.外部拦截法,也就是ViewGroup去做处理,ViewGroup重新onInterceptToucEvent,拦截除了ACTION_DOWN以外的其他事件,所以ACTION_DOWN必须返回false,要不然后续的ACTION_MOVE、ACTION_UP就到不了子View了,不过这块也是根据实际情况具体去写

2.内部拦截法,也就是子View去做处理,子View重写dispatchTouchEvent,需要子元素配合requestDisallowInterceptTouchEvent方法才能正常工作;父元素需要默认拦截除ACTION_DOWN以外的事件,这样子元素调用parent.requestDisallowInterceptTouchEvent(false)方法时,父元素才能继续拦截需要的事件。(ACTION_DOWN事件不受requestDisallowInterceptTouchEvent方法影响,所以一旦父元素拦截ACTION_DOWN事件,那么所有元素都无法传递到子元素去)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值