事件分发机制原理及其分析

     先给大家讲讲什么是事件分发?大家知道Android中的视图是由一个个View嵌套构成的层级视图,即一个View里包含有子View,而这个子View里面又可以再添加View。当用户触摸屏幕产生一系列事件时,事件会由高到低,由外向内依次传递,最终把事件交到一个具体的View手上处理,这个传递的过程就叫做事件分发。从手触摸屏幕开始所产生一系列MotionEvent事件,将事件传递...
摘要由CSDN通过智能技术生成

     

先给大家讲讲什么是事件分发?

大家知道Android中的视图是由一个个View嵌套构成的层级视图,即一个View里包含有子View,而这个子View里面又可以再添加View。当用户触摸屏幕产生一系列事件时,事件会由高到低,由外向内依次传递,最终把事件交到一个具体的View手上处理,这个传递的过程就叫做事件分发。

从手触摸屏幕开始所产生一系列MotionEvent事件,将事件传递到具体的某一个View的过程就叫做事件分发。

Android将触摸事件统一封装成MontionEvent类,以Down事件开始,Up事件结束,中间可能会产生其实事件(例如Move),组成一个完整的事件系列。

同时事件分发又有三个重要的方法:

boolean dispatchTouchEvent(MotionEvent e)

如果事件能够传递给当前View,此方法一定会被调用,意味着当前View接受到事件。

boolean onInterceptTouchEvent()

在dispatchTouchEvent方法中调用,用来判断是否要拦截当前事件。基本上不拦截事件。

boolean onTouchEvent()

在dispatchTouchEvent方法中调用,用来处理点击事件。返回ture则意味事件被消费。

三大方法有着千丝万缕的关系。调用dispatchTouchEvent()方法则说明事件已经交到该View手上了,接来下要么View自己拦截(onInterceptTouchEvent())处理事件,要么传递给子View。

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

​

举个例子: 小明的父亲准备将传家宝传给小明(dispatchTouchEvent)。小明拿到传家宝后,立马对自己的儿子进行了重重考核(onInterceptTouchEvent),最终小明觉得自己的儿子太不争气了。就决定不把传家宝交给儿子,把宝贝拿去卖了换钱养老(onTouchEvent)。所以到这,该宝贝传到小明手上就断了传承,同理事件也就意味着结束了。

当然如果小明儿子挺争气的,小明就会把传家宝传给儿子。到了小明的儿子手上又如此向下反复传承。直至有后代自己把宝贝处理了,断了传承,事件也才被消费结束。

小明有后代的情况下才有义务把传家宝传下去,所以他会把传家宝传给符合自己要求的儿子,如果儿子不符合要求,则自己拿来养老。所以ViewGroup的dispatchTouchEvent()一般都不拦截事件,只有在很苛刻的条件下才会主动拦截。接下来再找到符合条件的子View,把事件传递给他。

如果小明终无后人,则传家宝到小明手上后就断了传承,自己连传和不传的选择都没有,只能自己想办法给处理了。所以View没有onInterceptTouchEvent()方法,交到View手上也就意味着事件即将处理。(此View非彼View,例如TextView这种单独的View,不能再添加子View)

从那儿开始发事件?

事件最终会交给一个View处理,那事件最开始是从那儿传递的呢?Activity。 产生事件最先会交给Activity,再依次向下传递。

​
Activity
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
//空实现
onUserInteraction();
}
if (getWindow().superDispatchTouchEvent(ev)) {
return true;
}
return onTouchEvent(ev);
}

PhoneWindow

@Override
public boolean superDispatchTouchEvent(MotionEvent event) {
return mDecor.superDispatchTouchEvent(event);
}

DecorView

public boolean superDispatchTouchEvent(MotionEvent event) {

return super.dispatchTouchEvent(event);
}

​

Activity会将事件传递给Window,window又会向下继续传递。如果最终都没有View消费事件(superDispatchTouchEvent返回false),则Activity会自己调用onTouchEvent()方法处理事件。

 
if (getWindow().superDispatchTouchEvent(ev)) {
return true;
}
return onTouchEvent(ev);

而PhoneWindow又会把事件传递给DecorVi

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

万能程序者

你的鼓励是我不断学习前进的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值