MotionEvent
1.简介
MotionEvent
是Android系统中一个非常重要的类,它代表了屏幕上发生的触摸事件。- 当用户在屏幕上触摸、滑动或者长按时,都会生成一个
MotionEvent
对象,这个对象包含了触摸动作的各种信息。
2.事件类型
-
ACTION_DOWN:手指初次接触到屏幕时触发,这是触摸系列中的第一个事件。
-
ACTION_UP:手指离开屏幕时触发,这是触摸系列中的最后一个事件。
-
ACTION_MOVE:手指 在屏幕上滑动时触发,会多次触发。如果一个视图已经处理了
ACTION_DOWN
,它将连续接收到ACTION_MOVE
事件,直到用户抬起手指。 -
ACTION_POINTER_DOWN: 当用户在屏幕上按下第二个或第三个手指时触发。这个事件包含了一个
actionIndex
参数,用于区分是哪个触点的动作。 -
ACTION_POINTER_UP:当用户抬起第二个或第三个手指时触发。同样,这个事件也有一个
actionIndex
参数。事件中有
Pointer
的概念,一个pointer就代表一个触摸点,每个pointer都有自己的事件类型,也有自己的横轴坐标值。 -
ACTION_CANCEL:事件被上层拦截时触发。
-
ACTION_OUTSIDE: 当触摸事件发生在视图的边界外时触发。
事件分发
1.核心方法
-
dispatchTouchEvent
- 是ViewGroup中的一个非常重要的方法,它负责分发触摸事件。
- 当一个触摸事件发生时,首先由
dispatchTouchEvent
方法处理。 - 这个方法会根据事件类型以及视图层次结构(View树)的布局,决定是否消费这个事件,以及是否将事件传递给子视图。
- 返回值表示是否消费了当前事件。(返回true表示事件被消费,本次的事件终止。返回false表示View以及子View均没有消费事件,将调用父View的onTouchEvent方法)
public boolean dispatchTouchEvent(MotionEvent event)
-
onInterceptTouchEvent
- 用于在ViewGroup中决定是否拦截触摸事件,即是否要在子视图中处理这个事件。
- 这是ViewGroup特有的方法。
- 这个方法在
dispatchTouchEvent
中被调用,在决定是否传递给子视图之前执行。 - 返回true表示拦截了事件,那么事件将不再向下分发而是调用View本身的onTouchEvent方法。
- 返回false表示不做拦截,事件将向下分发到子View的dispatchTouchEvent方法。
public boolean onInterceptTouchEvent(MotionEvent ev)
-
onTouchEvent
- 是View类的方法,用于处理具体的触摸事件。
- 对于一个ViewGroup,当它决定拦截一个触摸事件并自行处理时,它会调用子视图的
onTouchEvent
方法。 - 如果
onTouchEvent
返回true
,表示事件被消耗;如果返回false
,表示事件未被消耗,会继续传递给父视图(调用父View的onTouchEvent方法)或其他相关视图。
public boolean onTouchEvent(MotionEvent ev)
2.不同事件类型的传递方式
-
ACTION_DOWN
当用户触摸屏幕时触发。这是触摸序列的开始。
MotionEvent
从触摸的视图开始,沿着视图树向下传递,直到找到一个消费事件的视图。如果没有任何视图消费这个事件,它最终会被传递到根视图。 -
ACTION_UP
当用户抬起手指时触发。这是触摸序列的结束。与
ACTION_DOWN
类似,MotionEvent
从触摸的视图开始,沿着视图树向下传递,直到找到一个消费事件的视图。 -
ACTION_MOVE
当用户在触摸屏上移动手指时触发。这个事件会传递给当前焦点视图,如果焦点视图是一个可以接收触摸事件的视图(如
View.OnTouchListener
或GestureDetector
),它将处理这个事件。 -
ACTION_CANCEL
当触摸事件因为某些原因被取消时触发,例如视图被回收。这个事件会传递到根视图。
-
ViewGroup,先要走分发流程,再走处理流程。View,只能走处理流程
3.事件分发流程
-
判断事件是否拦截,不拦截则分发(只有down事件才分发)。
-
分发或者处理:
-
拦截:相当于你是最后一个,事件到底处不处理。
-
不拦截:进行分发。全部不处理和拦截流程一样。
-
-
判断下属View能否接收事件:
- View是不是可见的(VISIBLE)。
- 是不是具有动画。