Android事件分发机制简述

一、被分发的对象

被分发的对象是那些?被分发的对象是用户触摸屏幕而产生的点击事件,事件主要包括:按下、滑动、抬起与取消。这些事件被封装成MotionEvent对象。该对象中的主要事件如下表所示:

事件触发场景单次触发的次数
MotionEvent.ACTION_DOWN在屏幕按下时1次
MotionEvent.ACTION_MOVE在屏幕上滑动时0次或多次
MotionEvent.ACTION_UP在屏幕抬起时0次或1次
MotionEvent.ACTION_CANCLE滑动超出控件边界时0次或1次

按下、滑动、抬起、取消这几种事件组成了一个事件流。事件流以按下为开始,中间可能有多次滑动,以抬起或取消结束。

二、分发事件的组件

分发事件的组件:分发事件者,包括Activity、View和ViewGroup。它们三者的一般结构为:
在这里插入图片描述

组件特点例子
Activity视图类如MainActivity
ViewGroupView的容器,可以包含若干View各种布局类
ViewUI类组件的基类如Button、textview

三、分发的核心方法

负责对事件进行分发的方法主要有三个
dispatchTouchEvent()
onTouchEvent()
onInterceptTouchEvent()
不是所有的组件都有这三个方法:

组件dispatchTouchEventonTouchEventonInterceptTouchEvent
Activity存在存在不存在
ViewGroup存在存在存在
View存在存在不存在

四、事件分发过程

事件分发流程
分发方法dispatchTouchEvent

Activity的dispatchTouchEvent方法

public boolean dispatchTouchEvent(MotionEvent ev) {
    if (child.dispatchTouchEvent(ev)) {
        return true;    //如果子View消费了该事件,则返回TRUE,让调用者知道该事件已被消费
    } else {
        return onTouchEvent(ev);    //如果子View没有消费该事件,则调用自身的onTouchEvent尝试处理。
    }
}

当事件传递给Activity后,它先将事件分发给子View处理。

  • 如果经过子View层层传递或处理后,该事件被消费了(即返回了true),则Activity的分发方法也返回true,同样也表示该事件已经被消费了。
  • 如果经过子View层层传递或处理后,该事件没有被消费(即返回了false),则Activity的分发方法就不会返回true了,而是调用onTouchEvent()去处理,看其实际的处理情况。
  • 如果onTouchEvent消费了事件,那依然能返回true(表示已消费事件),这个true作为dispatchTouchEvent的返回值,让调用它的对象知道该Activity已经消费了事件。
  • 如果onTouchEvent没有消费该事件,那就返回false(表示未消费事件),这个false作为dispatchTouchEvent的返回值,让调用它的对象知道该Activity没有消费事件,需要继续处理。

ViewGroup的dispatchTouchEvent方法

public boolean dispatchTouchEvent(MotionEvent ev) {
    if (!onInterceptTouchEvent(ev)) {
        return child.dispatchTouchEvent(ev);    //不拦截,则传给子View进行分发处理
    } else {
        return onTouchEvent(ev);    //拦截事件,交由自身对象的onTouchEvent方法处理
    }
}

ViewGroup的dispatchTouchEvent 多了一个onInterceptTouchEvent方法。当事件传入时,首先会调用onInterceptTouchEvent。

  • 如果该方法返回了false(表示不拦截),则交给子View去调用dispatchTouchEvent()方法
  • 如果该方法返回了true(表示拦截),则直接交给该ViewGroup对象的onTouchEvent(ev)方法处理,具体是否能处理以onTouchEvent()的实际情况为准。
  • 如果 ViewGroup 重写了 onInterceptTouchEvent或者onTouchEvent 并满足拦截条件就会返回true,常见的有自定义手势监听,滑动处理等

View的dispatchTouchEvent方法

public boolean dispatchTouchEvent(MotionEvent ev) {
    //如果该对象的监听成员变量不为空,则会调用其onTouch方法,
    if (mOnTouchListener != null && mOnTouchListener.onTouch(this, event)) {
        return true;    //若onTouch方法返回TRUE,则表示消费了该事件,则dispachtouTouchEvent返回TRUE,让其调用者知道该事件已被消费。
    }
    return onTouchEvent(ev);    //若监听成员为空或onTouch没有消费该事件,则调用对象自身的onTouchEvent方法处理。
}

方法调用后,会先对mOnTouchListener判空,如果之前Set了Listener,则会调用其onTouch方法。

  • 若onTouch方法返回TRUE,则dispatchTouchEvent也会返回TRUE,表示消费该事件。
  • 若onTouch方法返回FALSE,或者mOnTouchListener本来就是空,则调用自身的onTouchEvent()来处理,是否消费事件,可以由其返回值判断。
  • 4
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值