motionevent android,Android开发中MotionEvent的传递 学习笔记

最近在写一个自定义的ViewGroup,涉及到MotionEvent的分发。看了一些资料后发现还是有点迷迷糊糊的,所以动手写了Demo,打log来观察到底是怎么传递的。希望以下内容能帮到各位。

环境说明:

整个界面如下所示:

a7809cd388d3

蓝框是 ViewGroup,红框是个宽高都是 MATCH_PARENT 的 View

蓝框是个继承于LinearLayout的自定义ViewGroup,类名为VGDemo,在onInterceptTouchEvent、dispatchTouchEvent和onTouchEvent中添加了打log的语句。

红框是个继承于View的自定义View,类名为VDemo,在dispatchTouchEvent和onTouchEvent中添加了打log的语句,它在蓝框之内,宽高都是MATCH_PARENT。

操作是,在红框范围内,单指,按下 → 滑动 → 抬起。

在情况分析中每一份logcat的输出都是在执行了上述操作后的输出,在每一次执行操作之前都有清空logcat的行为,为了不引入上一次的输出,以免妨碍观察。

情况分析与总结:

假设整个链路上所有自定义添加了打log的方法都是return false的话,整个流程是

dispatchTouchEvent(ViewGroup) → onInterceptTouchEvent(ViewGroup)

→ dispatchTouchEvent(View) → onTouchEvent(View)

→ onTouchEvent(ViewGroup)

此时意味着任何事件在整个链路上都没有被消费,自然也包括DOWN事件,那么这样只会有DOWN事件会传入这个链路,又因为DOWN事件没有被消费,那么接下来直到下一个DOWN事件之前的任何点击事件都不会被传入这个链路中。

logcat的输出为:

10-31 10:22:44.286 testapplication.view.VGDemo: dispatchTouchEvent: ACTION_DOWN

10-31 10:22:44.286 testapplication.view.VGDemo: onInterceptTouchEvent: ACTION_DOWN

10-31 10:22:44.287 testapplication.view.VDemo: dispatchTouchEvent: ACTION_DOWN

10-31 10:22:44.287 testapplication.view.VDemo: onTouchEvent: ACTION_DOWN

10-31 10:22:44.288 testapplication.view.VGDemo: onTouchEvent: ACTION_DOWN

如果某个DOWN事件在最内层的onTouchEvent消费了,那么接下来直到下一个DOWN事件之前的任何点击事件,不管最内层的onTouchEvent还会不会消费它们,它们的终点都是这个最内层的onTouchEvent,不会传递到VG的onTouchEvent处。即此时的分发链路为:

dispatchTouchEvent(ViewGroup) → onInterceptTouchEvent(ViewGroup) → dispatchTouchEvent(View) → onTouchEvent(View)

在最内层的onTouchEvent中指定消费了DOWN事件后的logcat输出:

10-31 10:19:17.544 testapplication.view.VGDemo: dispatchTouchEvent: ACTION_DOWN

10-31 10:19:17.544 testapplication.view.VGDemo: onInterceptTouchEvent: ACTION_DOWN

10-31 10:19:17.544 testapplication.view.VDemo: dispatchTouchEvent: ACTION_DOWN

10-31 10:19:17.544 testapplication.view.VDemo: onTouchEvent: ACTION_DOWN

10-31 10:19:17.569 testapplication.view.VGDemo: dispatchTouchEvent: ACTION_MOVE

10-31 10:19:17.569 testapplication.view.VGDemo: onInterceptTouchEvent: ACTION_MOVE

10-31 10:19:17.569 testapplication.view.VDemo: dispatchTouchEvent: ACTION_MOVE

10-31 10:19:17.569 testapplication.view.VDemo: onTouchEvent: ACTION_MOVE

10-31 10:19:17.723 testapplication.view.VGDemo: dispatchTouchEvent: ACTION_MOVE

10-31 10:19:17.724 testapplication.view.VGDemo: onInterceptTouchEvent: ACTION_MOVE

10-31 10:19:17.724 testapplication.view.VDemo: dispatchTouchEvent: ACTION_MOVE

10-31 10:19:17.724 testapplication.view.VDemo: onTouchEvent: ACTION_MOVE

....四条重复,循环

10-31 10:19:18.072 testapplication.view.VGDemo: dispatchTouchEvent: ACTION_MOVE

10-31 10:19:18.072 testapplication.view.VGDemo: onInterceptTouchEvent: ACTION_MOVE

10-31 10:19:18.072 testapplication.view.VDemo: dispatchTouchEvent: ACTION_MOVE

10-31 10:19:18.072 testapplication.view.VDemo: onTouchEvent: ACTION_MOVE

10-31 10:19:18.072 testapplication.view.VGDemo: dispatchTouchEvent: ACTION_UP

10-31 10:19:18.072 testapplication.view.VGDemo: onInterceptTouchEvent: ACTION_UP

10-31 10:19:18.072 testapplication.view.VDemo: dispatchTouchEvent: ACTION_UP

10-31 10:19:18.072 testapplication.view.VDemo: onTouchEvent: ACTION_UP

在2的情形下,如果VG在onInterceptTouchEvent中对接下来直到下一个DOWN事件之前的任何一个点击事件进行拦截(即返回true),那么从拦截事件开始到下一个DOWN事件之前的任何点击事件都会走

dispatchTouchEvent(ViewGroup) → onTouchEvent(ViewGroup)

这个链路,不再经过其他流程;而拦截这个事件的同时,VG会分发个CANCEL的事件给原来消费了DOWN事件的子View。

指定对MOVE事件进行拦截时的logcat输出如下:

10-31 10:11:00.321 testapplication.view.VGDemo: dispatchTouchEvent: ACTION_DOWN

10-31 10:11:00.321 testapplication.view.VGDemo: onInterceptTouchEvent: ACTION_DOWN

10-31 10:11:00.321 testapplication.view.VDemo: dispatchTouchEvent: ACTION_DOWN

10-31 10:11:00.321 testapplication.view.VDemo: onTouchEvent: ACTION_DOWN

10-31 10:11:00.340 testapplication.view.VGDemo: dispatchTouchEvent: ACTION_MOVE

10-31 10:11:00.340 testapplication.view.VGDemo: onInterceptTouchEvent: ACTION_MOVE

10-31 10:11:00.340 testapplication.view.VDemo: dispatchTouchEvent: ACTION_CANCEL

10-31 10:11:00.340 testapplication.view.VDemo: onTouchEvent: ACTION_CANCEL

10-31 10:11:00.357 testapplication.view.VGDemo: dispatchTouchEvent: ACTION_MOVE

10-31 10:11:00.357 testapplication.view.VGDemo: onTouchEvent: ACTION_MOVE

10-31 10:11:00.374 testapplication.view.VGDemo: dispatchTouchEvent: ACTION_MOVE

10-31 10:11:00.374 testapplication.view.VGDemo: onTouchEvent: ACTION_MOVE

10-31 10:11:00.391 testapplication.view.VGDemo: dispatchTouchEvent: ACTION_MOVE

10-31 10:11:00.391 testapplication.view.VGDemo: onTouchEvent: ACTION_MOVE

10-31 10:11:00.409 testapplication.view.VGDemo: dispatchTouchEvent: ACTION_MOVE

10-31 10:11:00.409 testapplication.view.VGDemo: onTouchEvent: ACTION_MOVE

10-31 10:11:00.426 testapplication.view.VGDemo: dispatchTouchEvent: ACTION_MOVE

10-31 10:11:00.426 testapplication.view.VGDemo: onTouchEvent: ACTION_MOVE

10-31 10:11:00.444 testapplication.view.VGDemo: dispatchTouchEvent: ACTION_MOVE

10-31 10:11:00.444 testapplication.view.VGDemo: onTouchEvent: ACTION_MOVE

10-31 10:11:00.743 testapplication.view.VGDemo: dispatchTouchEvent: ACTION_UP

10-31 10:11:00.743 testapplication.view.VGDemo: onTouchEvent: ACTION_UP

在2的情形下,如果VG在dispatchTouchEvent中对接下来直到下一个DOWN事件之前的任何一个点击事件进行分发(即返回true),那么对于指定的分发事件,它们都会只经过dispatchTouchEvent(ViewGroup),不会经过其他事件(所以如果是要分发到VG的onTouchEvent,请务必要自行在dispatchTouchEvent那里调用onTouchEvent方法!),也不会通知子View一个CANCEL事件;而对于没有指定分发的事件,则是仍旧走2中的分发链路。

指定对MOVE事件进行分发时的logcat输出如下:

10-31 09:32:39.036 testapplication.view.VGDemo: dispatchTouchEvent: ACTION_DOWN

10-31 09:32:39.036 testapplication.view.VGDemo: onInterceptTouchEvent: ACTION_DOWN

10-31 09:32:39.036 testapplication.view.VDemo: dispatchTouchEvent: ACTION_DOWN

10-31 09:32:39.037 testapplication.view.VDemo: onTouchEvent: ACTION_DOWN

10-31 09:32:39.049 testapplication.view.VGDemo: dispatchTouchEvent: ACTION_MOVE

10-31 09:32:39.084 testapplication.view.VGDemo: dispatchTouchEvent: ACTION_MOVE

10-31 09:32:39.104 testapplication.view.VGDemo: dispatchTouchEvent: ACTION_MOVE

10-31 09:32:39.122 testapplication.view.VGDemo: dispatchTouchEvent: ACTION_MOVE

10-31 09:32:39.139 testapplication.view.VGDemo: dispatchTouchEvent: ACTION_MOVE

10-31 09:32:39.157 testapplication.view.VGDemo: dispatchTouchEvent: ACTION_MOVE

10-31 09:32:39.174 testapplication.view.VGDemo: dispatchTouchEvent: ACTION_MOVE

10-31 09:32:39.192 testapplication.view.VGDemo: dispatchTouchEvent: ACTION_MOVE

10-31 09:32:39.209 testapplication.view.VGDemo: dispatchTouchEvent: ACTION_MOVE

10-31 09:32:39.226 testapplication.view.VGDemo: dispatchTouchEvent: ACTION_MOVE

10-31 09:32:39.245 testapplication.view.VGDemo: dispatchTouchEvent: ACTION_MOVE

10-31 09:32:39.261 testapplication.view.VGDemo: dispatchTouchEvent: ACTION_MOVE

10-31 09:32:39.488 testapplication.view.VGDemo: dispatchTouchEvent: ACTION_UP

10-31 09:32:39.488 testapplication.view.VGDemo: onInterceptTouchEvent: ACTION_UP

10-31 09:32:39.488 testapplication.view.VDemo: dispatchTouchEvent: ACTION_UP

10-31 09:32:39.489 testapplication.view.VDemo: onTouchEvent: ACTION_UP

如果DOWN事件在VG的onTouchEvent中被消耗,那么接下来直到下一个DOWN事件之前的任何点击事件都是走

dispatchTouchEvent(ViewGroup) → onTouchEvent(ViewGroup)

这个链路,不会走到View里面的任何方法,也不会走到VG的onInterceptTouchEvent方法。

logcat输出为:

10-31 11:18:22.980 testapplication.view.VGDemo: dispatchTouchEvent: ACTION_DOWN

10-31 11:18:22.980 testapplication.view.VGDemo: onInterceptTouchEvent: ACTION_DOWN

10-31 11:18:22.980 testapplication.view.VDemo: dispatchTouchEvent: ACTION_DOWN

10-31 11:18:22.980 testapplication.view.VDemo: onTouchEvent: ACTION_DOWN

10-31 11:18:22.980 testapplication.view.VGDemo: onTouchEvent: ACTION_DOWN

10-31 11:18:22.987 testapplication.view.VGDemo: dispatchTouchEvent: ACTION_MOVE

10-31 11:18:22.987 testapplication.view.VGDemo: onTouchEvent: ACTION_MOVE

10-31 11:18:23.003 testapplication.view.VGDemo: dispatchTouchEvent: ACTION_MOVE

10-31 11:18:23.003 testapplication.view.VGDemo: onTouchEvent: ACTION_MOVE

10-31 11:18:23.021 testapplication.view.VGDemo: dispatchTouchEvent: ACTION_MOVE

10-31 11:18:23.021 testapplication.view.VGDemo: onTouchEvent: ACTION_MOVE

10-31 11:18:23.038 testapplication.view.VGDemo: dispatchTouchEvent: ACTION_MOVE

10-31 11:18:23.038 testapplication.view.VGDemo: onTouchEvent: ACTION_MOVE

10-31 11:18:23.056 testapplication.view.VGDemo: dispatchTouchEvent: ACTION_MOVE

10-31 11:18:23.056 testapplication.view.VGDemo: onTouchEvent: ACTION_MOVE

10-31 11:18:23.073 testapplication.view.VGDemo: dispatchTouchEvent: ACTION_MOVE

10-31 11:18:23.073 testapplication.view.VGDemo: onTouchEvent: ACTION_MOVE

10-31 11:18:23.090 testapplication.view.VGDemo: dispatchTouchEvent: ACTION_MOVE

10-31 11:18:23.090 testapplication.view.VGDemo: onTouchEvent: ACTION_MOVE

10-31 11:18:23.108 testapplication.view.VGDemo: dispatchTouchEvent: ACTION_MOVE

10-31 11:18:23.108 testapplication.view.VGDemo: onTouchEvent: ACTION_MOVE

10-31 11:18:23.125 testapplication.view.VGDemo: dispatchTouchEvent: ACTION_MOVE

10-31 11:18:23.125 testapplication.view.VGDemo: onTouchEvent: ACTION_MOVE

10-31 11:18:23.143 testapplication.view.VGDemo: dispatchTouchEvent: ACTION_MOVE

10-31 11:18:23.143 testapplication.view.VGDemo: onTouchEvent: ACTION_MOVE

10-31 11:18:23.160 testapplication.view.VGDemo: dispatchTouchEvent: ACTION_MOVE

10-31 11:18:23.160 testapplication.view.VGDemo: onTouchEvent: ACTION_MOVE

10-31 11:18:23.178 testapplication.view.VGDemo: dispatchTouchEvent: ACTION_MOVE

10-31 11:18:23.178 testapplication.view.VGDemo: onTouchEvent: ACTION_MOVE

10-31 11:18:23.191 testapplication.view.VGDemo: dispatchTouchEvent: ACTION_MOVE

10-31 11:18:23.191 testapplication.view.VGDemo: onTouchEvent: ACTION_MOVE

10-31 11:18:23.191 testapplication.view.VGDemo: dispatchTouchEvent: ACTION_UP

10-31 11:18:23.191 testapplication.view.VGDemo: onTouchEvent: ACTION_UP

参考资料:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值