你应该了解一下 Android 的事件分发机制

本文深入探讨Android的事件分发、拦截与消费机制,通过自定义ViewGroup和View,结合MainActivity,详细解释了onTouchEvent、dispatchTouchEvent及onInterceptTouchEvent的作用与区别,帮助读者更好地理解触摸事件的传递流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关于 Android 的事件分发机制,自我感觉还是比较乱的,要弄懂是要费上一点功夫,网上有很多关于这方面的文章,我在学习的时候也看了一下些,但我还是想用自己的语言总结一下这部分的知识点。

首先有三个词:分发拦截消费

在这之前,我们先简单的创建一个活动,

界面布局如下,自定义个 ViewGroup 继承于 RelativeLayout 自定义一个 View 继承于TextView 

为什么不直接使用 RelativeLayout 和 TextView 呢?

因为接下来要为这两个控件和 MainActivity 都重写 onTouchEvent() 方法,并且打印Log

@Override
public boolean onTouchEvent(MotionEvent event) {
    Log.e("MyLayout","onTouchEvent");
    return super.onTouchEvent(event);
}
//MyTextView和MainActivity同理

Log打印如下:

分析一下:可以看出触摸事件是从 MyText 开始的 再 传递给 MyLayout 最后回到 MainActivity。那为什么不是从 MainActivity 开始的呢?这个就涉及到事件的 分发机制 

我们还是先从简单消费机制着手

我们会发现 onTouchEvent() 这个方法是有返回值的,这个返回值是干什么用的呢?

尝试把 MyText 的 onTouchEvent() 返回值改成 true:

@Override
public boolean onTouchEvent(MotionEvent event) {
    Log.e("MyText","onTouchEvent");
    return true;
}

再次打印Log:

发现只打印了 MyText  的 onTouchEvent 了,这是因为 这个事件被 MyText 消费了,所以 return true 就代表消费事件,事件将不会在往上传递!

返回 false :表示不消费此事件,如果都不消费最终会由 MainActivity 消费

接着讲讲 分发:

接着为这两个控件和MainActivity添加 dispathchTouchEvent() 方法,并且打印Log

@Override
public boolean dispatchTouchEvent(MotionEvent event) {
    Log.e("MyText","dispatchTouchEvent");
    return super.dispatchTouchEvent(event);
}

Log打印如下:

对比一下上次打印的信息,发现 dispathchTouchEvent() 是从MainActiviy开始往下传递的,这就是事件的分发方法

事件从顶层开始往底层分发,最后从底层的触摸事件传递回顶层。

观察一下 dispathchTouchEvent()  方法,发现这个方法也是有返回值的

尝试把 MyLayout 的 dispathchTouchEvent() 方法的返回值改为 true

@Override
public boolean dispatchTouchEvent(MotionEvent event) {
    Log.e("MainActivity","dispatchTouchEvent");
    return true;
}

看一眼Log打印信息:

消费 是同样的道理,如果返回 true 则不再往下分发事件,并且消费事件。

那试试返回 false,修改 MyLayout 中的 dispatchTouchEvent() 方法返回值为 false

@Override
public boolean dispatchTouchEvent(MotionEvent event) {
    Log.e("MyLayout","dispatchTouchEvent");
    return false;
}

对比一下 返回 true 的情况,发现返回 false 就不会把事件消费掉,而是直接往上传递。

分发 也就到这里结束了。

最后在讲一讲 拦截

拦截 是这个方法:onInterceptTouchEvent() 只有  ViewGroup 才能使用拦截。那么在 MyLayout 中重写这个方法并打印Log:

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    Log.e("MyLayout","onInterceptTouchEvent");
    return super.onInterceptTouchEvent(ev);
}

这个方法会在 分发后被调用,那么拦截是来做什么的呢?

我们把 返回值改为 true,再看一眼Log打印

对比一下分发的情况,发现 MyLayout 的 onTouchEvent 也被执行了!这就是拦截和分发的区别。

返回false 的话则表示不拦截,事件会接着传递。

那么整个 Android 的事件传递机制到这就基本讲完了。最后在文尾补充一张 流程图 帮助大家更好理解!

如果这篇文章能对你起到一点帮助,那我倍感荣幸

如果有什么地方讲的不对 欢迎在评论中指出,我会加以改正万分感谢!

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值