欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

一个最简单的屏幕触摸动作,理解事件分发的3个方法

程序员文章站 2022-05-06 09:11:07
...

前言

android中的事件类型分为按键事件和屏幕触摸事件,Touch事件是屏幕触摸事件的基础事件。

一次屏幕触摸会发生什么?

触发了一系列Touch事件:ACTION_DOWN->ACTION_MOVE->ACTION_MOVE->ACTION_MOVE…->ACTION_MOVE->ACTION_UP。到底有多少个MOVE呢?我也不知道,我写demo测试的时候点击一下是打印了3条。

当屏幕中包含一个ViewGroup,而这个ViewGroup又包含一个子view,这个时候android系统如何处理Touch事件呢?到底是ViewGroup来处理Touch事件,还是子view来处理Touch事件呢?先留个疑问。

解决疑问前,先要理清楚ViewGroup这个类中,和TouchEvent处理密切相关的3个方法:

  • public boolean dispatchTouchEvent(MotionEvent ev) 这个方法用来分发TouchEvent
  • public boolean onInterceptTouchEvent(MotionEvent ev) 这个方法用来拦截TouchEvent(这个方法在View类中没有)
  • public boolean onTouchEvent(MotionEvent ev) 这个方法用来处理TouchEvent

接下来我们来理一下逻辑

当TouchEvent发生时,首先交互界面(Activity或者Fragment)将TouchEvent传递给最顶层的View, TouchEvent最先到达最顶层 view 的 dispatchTouchEvent ,然后由dispatchTouchEvent 方法进行分发,如果dispatchTouchEvent返回true ,就不往下传递了,如果dispatchTouchEvent返回 false ,则交给这个 view 的 interceptTouchEvent 方法来决定是否要拦截这个事件,如果 interceptTouchEvent 返回 true ,也就是拦截掉了,则交给它的 onTouchEvent 来处理,如果 interceptTouchEvent 返回 false ,那么就传递给子 view ,由子 view 的 dispatchTouchEvent 再来开始这个事件的一次分发。如果事件传递到某一层, 被onTouchEvent 处理了,那这一次事件算是结束了。

看一道小米的面试题

一个最简单的屏幕触摸动作,理解事件分发的3个方法

先回忆一下之前的知识

1、最开始接收事件的是最外层的对象。
2、最外层对象会依次调用dispatchTouchEvent 、onInterceptTouchEvent 。(一般情况:有儿子View,分发+不拦截)
3、事件传递到某层的儿子View,onTouchEvent处理了。

问题解答
ACTION_DOWN在3个界面传递;ACTION_MOVE在A、B界面传递,B拦截了并调用onTouchEvent处理了。ACTION_UP在A、B界面传递。

问题分析
ACTION_DOWN没有限制;ACTION_MOVE到B的时候由于onInterceptTouchEvent拦截了,被B处理,C收不到;ACTION_UP由于B拦截了MOVE,已经处理了,也会直接在B调用onTouchEvent处理。

打印日志

A

12-05 18:03:18.871 6113-6113/com.phz.testtouchevent E/ALayout: dispatchTouchEvent:ACTION_DOWN
12-05 18:03:18.871 6113-6113/com.phz.testtouchevent E/ALayout: onInterceptTouchEvent:ACTION_DOWN
12-05 18:03:18.889 6113-6113/com.phz.testtouchevent E/ALayout: dispatchTouchEvent:ACTION_MOVE
12-05 18:03:18.889 6113-6113/com.phz.testtouchevent E/ALayout: onInterceptTouchEvent:ACTION_MOVE
12-05 18:03:18.906 6113-6113/com.phz.testtouchevent E/ALayout: dispatchTouchEvent:ACTION_MOVE
12-05 18:03:18.906 6113-6113/com.phz.testtouchevent E/ALayout: onInterceptTouchEvent:ACTION_MOVE
12-05 18:03:18.909 6113-6113/com.phz.testtouchevent E/ALayout: dispatchTouchEvent:ACTION_UP
12-05 18:03:18.910 6113-6113/com.phz.testtouchevent E/ALayout: onInterceptTouchEvent:ACTION_UP

B

12-05 18:03:18.871 6113-6113/com.phz.testtouchevent E/BLayout: dispatchTouchEvent:ACTION_DOWN
12-05 18:03:18.871 6113-6113/com.phz.testtouchevent E/BLayout: onInterceptTouchEvent:ACTION_DOWN
12-05 18:03:18.889 6113-6113/com.phz.testtouchevent E/BLayout: dispatchTouchEvent:ACTION_MOVE
12-05 18:03:18.889 6113-6113/com.phz.testtouchevent E/BLayout: onInterceptTouchEvent:ACTION_MOVE
12-05 18:03:18.906 6113-6113/com.phz.testtouchevent E/BLayout: dispatchTouchEvent:ACTION_MOVE
12-05 18:03:18.906 6113-6113/com.phz.testtouchevent E/BLayout: onTouchEvent:ACTION_MOVE
12-05 18:03:18.910 6113-6113/com.phz.testtouchevent E/BLayout: dispatchTouchEvent:ACTION_UP
12-05 18:03:18.910 6113-6113/com.phz.testtouchevent E/BLayout: onTouchEvent:ACTION_UP

C

12-05 18:03:18.871 6113-6113/com.phz.testtouchevent E/CLayout: dispatchTouchEvent:ACTION_DOWN
12-05 18:03:18.871 6113-6113/com.phz.testtouchevent E/CLayout: onTouchEvent:ACTION_DOWN