移动开发:你以为事件分发很简单,但我却被问哭了...

今天上班第一天给大家娱乐一下,给大家讲讲事件分发,你可能会一笑:“别搞我呀,事件分发谁不知道呀。”

但是,今天的内容,可能真的有你不知道的。

注意:如果你对事件分发原理并不是太了解,那么需要先对事件分发有足够的了解,最后再进行后续的阅读。

下面开始正文,因为这个问题是与同事间交流产生,所以本文以对话形式呈现。

主角:

小 A,小 B。

小 A:B 啊,你给我言简意赅的讲讲事件分发的流程。

小 B:好嘞。

“事件分发是针对一次手势的过程,这个手势包含一次 ACTION_DOWN,多次 ACTION_MOVE,和一次 ACTION_UP”,在 ACTION_DOWN 的时候来决定本次事件的“TargetView”,该 View 会决定这次事件分发的事件流向。

父控件可以在 ACTION_DOWN或者 targetView不为空的情况下,进行拦截,如果拦截了 targetView 的事件,会给它发一个 ACTION_CANCEL。

小 A:回答的可以呀,我来考你几个问题。

小 B:尽管来。

小 A:你说一次事件分发过程中会有多次ACTION_POINT_DOWN吗?

小 B内心:这不是送分题么,看样子小 A 兄弟对于多指这块不太熟悉呀,这都能做为问题。

小 B:当然可以,多指的时候,你按下第一个手指,再按下第二个手指ACTION_POINTER_DOWN就来了。

你可以看看 ViewPager,ScrollView 这些官方类源码,都有多指的处理。

小 A:鬼魅一笑,然后那我再问你,一次事件分发过程中,可能会有多次ACTION_DOWN吗?

小 B:等等,如果我答对了,一瓶可乐。

小 A:好。

小 B:没有,只有你第一个手指按下才是 ACTION_DOWN,从第二个开始都是ACTION_POINTER_DOWN,当然了前提是你自己不修改 dispatchTouchEvent 分发逻辑哈,改了可不算,是不是要去买可乐了。

小 A:好,最后我再问你一个具体的问题,一个 LinearLayout 内部有两个 Button,当我第一个手指按在第一个 Button 上,第二个手指按在第二个 Button 上,这两个 Button哪个会收到 ACTION_DOWN?分别抬起每个手指,哪个 Button 的 Click 会被触发?

小 B:当然是第一个收到 ACTION_DOWN,那么应该也是第一个能触发 click。

小 A:不错不错,你先去做个实验,再决定要不要我去买可乐。

对话结束。

到这里大家觉得小 B 回答的怎么样?

先别往下看,自己想想自己的回答应该是什么,如果错了,麻烦给我买瓶可乐。

小 B 回去测试。

大吼一声:为了可乐!

快速写完 Demo,分为自定义了一个 MyLinearLayout,MyButton,复写dispatchTouchEvent,打上 Event 日志,再加上 onclick 事件日志。

按照之前的描述实验:

一个 LinearLayout 内部有两个 Button,当我第一个手指按在第一个 Button 上,第二个手指按在第二个 Button 上,这两个 Button哪个会收到 ACTION_DOWN?分别抬起每个手指,哪个 Button 的 Click 会被触发?

看到 Log,心凉了。

第一个手指按下第一个 Button 上,第一个 Button 收到 ACTION_DOWN。
第二个手指按在第二个 Button 上,第二个 Button 竟然也收到了 ACTION_DOWN。

分别抬起时,两个 Button 的 Click 依次触发。

注意:大家测试的时候,Button 可以搞大一些,两个 Button 距离远一些,防止误触。

小 B带着两瓶可乐来到小 A 面前,大哥赶紧给我讲讲。

小 A:

好,在非常早期,很多博客的事件分发代码都是基于 2.x 系列的,那会代码是这样的:

完整代码见这里

MotionTarget 就是一个 View。而在后续的代码,"targetView"已经不再是一个独立的 View 了,而是一个类似于链表。

// First touch target in the linked list of touch targets.
private TouchTarget mFirstTouchTarget;

private static final class TouchTarget {

    // The touched child view.
    public View child;

    // The next target in the target list.
    public TouchTarget next;
}

你顺着这个差异去看源码就明白了。

小 B:这波不亏,虽然亏了两瓶可乐,但是学到了。

好了,AB 角色结束,对话内容基本上是同事间日常对话,当然我故意润色了一些。

再次友情提示:在面试的时候,不要故意显摆你知道一个事件分发逻辑可能有多个 ACTION_DOWN,一定要分情况说清楚,因为面试官很可能没看过这篇文章,把你挂了别怪我...

最后

其实对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们!

 

这里是关于我自己的Android 学习,面试文档,视频收集大整理,有兴趣的伙伴们可以看看~

当程序员容易,当一个优秀的程序员是需要不断学习的,从初级程序员到高级程序员,从初级架构师到资深架构师,或者走向管理,从技术经理到技术总监,每个阶段都需要掌握不同的能力。早早确定自己的职业方向,才能在工作和能力提升中甩开同龄人。

最后如果你和小B错的一样,可乐我就不要了,点个赞可以吧~

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值