事件分发

2021-08-22  本文已影响0人  明飞

  一:事件分发基础知识讲解

   1.事件分发的”事件“是指什么?

即 用户触摸屏幕时产生的点击事件(Touch事件)。这个点击事件(Touch事件)会被封装成MotionEvent对象。从手指接触屏幕至手指离开屏幕这个过程产生的一系列事件。一般情况下,事件列都是以DOWN事件开始、UP事件结束,中间有无数的MOVE事件。

MotionEvent 事件类型:

MotionEvent.ACTION_DOWN  手指 初次接触到屏幕 时触发

MotionEvent.ACTION_MOVE    手指 在屏幕上滑动时触发,会多次触发

MotionEvent.ACTION_UP      手指 离开屏幕 时触发

MotionEvent.ACTION_CANCEL  事件 被上层拦截 时触发

2.事件分发的本质

将点击事件(MotionEvent)传递到某个具体的View。及我们说所的事件分发。

 3.事件在哪些对象之间进行传递?事件分发的流程顺序?

事件传递的对象:Activity、ViewGroup、View

事件传递的顺序:1个点击事件发生后,事件先传到Activity-->再传到ViewGroup-->再到View

4. 事件分发过程由哪些方法协作完成?(重点)

① dispatchTouchEvent()   当前事件传递的对象是否把某个点击事件分发传递给他的孩子。                                             

true :  当前事件传递的对象  当前点击事件分发给下一级ViewGroup,让下一级ViewGroup 再来分发这个点击事件       

false :   当前点击事件没有往下分发(表示当前点击事件分发结束了,但是还没有处理).   

那就需要在 viewGroup.OnTouchEvent()方法来处理这个点击事件)                                                                                              

②onTouchEvent() :   (在dispatchTouchEvent()方法内部执行)                                                                                      

         当前事件传递的对象 对 该点击事件 是否处理

   ③ onInterceptTouchEvent()  : (在ViewGroup的dispatchTouchEvent()方法内部执行)                                                 当前事件传递的对象 对 该点击事件是否进行拦截

  false (默认) 不拦截当前的点击事件,那么该事件会继续向下级子View 传递分发点击事件

  true (需手动复写onInterceptTouchEvent()其返回true) 拦截当前的点击事件,即点击事件停止往下传递

 二:事件分发机制流程详细分析

流程1:Activity对点击事件的分发流程

Android事件分发机制首先会将点击事件传递到Activity中,通过dispatchTouchEvent()方法进行点击事件分发。

dispatchTouchEvent()如何分发 这个点击事件? 这个点击事件分发给谁呢?

(1)Activity对点击事件的分发流程 简单点总结:

  Activity.dispatchTouchEvent()

  true    当前点击事件分发给下一级ViewGroup,让下一级ViewGroup 再来分发这个点击事件

  false    当前点击事件没有往下分发(表示当前点击事件分发结束了),

            (当前点击事件虽然结束了分发,但是还没有处理)那就需要在Acvity.dispatchTouchEvent() 方法内部的执行Activity.OnTouchEvent()方法来处理这个点击事件, 

            Activity.OnTouchEvent()  =true  被Activity 消费处理了该点击事件(点击事件在Windows边界外)   

              Activity.OnTouchEvent()  =false  Activity  没有处理消费该事件 (点击事件在Windows边界内)

(2)源码分析:这里略

Window类是抽象类,其唯一实现类 = PhoneWindow类

DecorView顶层View.DecorView类是PhoneWindow类的一个内部类.

DecorView继承自FrameLayout,是所有界面的父类.

FrameLayout是ViewGroup的子类,故DecorView的间接父类 = ViewGroup

调用父类ViewGroup.dispatchTouchEvent()方法去处理这个点击事件

所以Activity的事件分发(Activity.dispatchTouchEvent(),最终还是有 ViewGroup.dispatchTouchEvent()方法去处理这个点击事件ViewGroup.dispatchTouchEvent() =false  就是ViewGroup,不会把点击事件往下分发, 那么就执行Activity.onTouchEvent()方法, 有Activity处理这个点击事件。

流程2: ViewGroup对点击事件的分发流程

ViewGroup每次事件分发时,都需先调用viewGroup.onInterceptTouchEvent()询问是否拦截当前点击事件

需要结合ViewGroup 源码分析:

根据源码我们知道:viewgroup.dispatchTouchEvent()事件分发  返回true 或false 的判断条件是:

 (1)判断条件1:boolean disallowIntercept:是否禁用事件拦截的功能

   ① disallowIntercept = true  禁用事件拦截的功能,   viewGroup.onInterceptTouchEvent(ev)=false,

 ②disallowIntercept = false(默认是false)    不禁用事件拦截的功能

viewGroup.onInterceptTouchEvent(ev)=true,

boolean disallowIntercept:是否禁用事件拦截的功能(默认是false),可通过调用requestDisallowInterceptTouchEvent(boolean disallowIntercept)修改

(2) 判断条件2:boolean onInterceptTouchEvent()

onInterceptTouchEvent()=true,即拦截当前点击事件,从而跳出了该条件判断,

那么该点击事件不能继续向下级子View 传递了 

public ViewGroup extends View{

public boolean dispatchTouchEvent(MotionEvent ev) {

final boolean intercepted;

 final boolean disallowIntercept = (mGroupFlags &FLAG_DISALLOW_INTERCEPT) !=0;

if (!disallowIntercept) {

intercepted = onInterceptTouchEvent(ev);

}else {

intercepted =false;

}

}

}

流程3:View对点击事件的分发流程

这里需要特别注意的是,onTouch()的执行 先于onClick()

上一篇下一篇

猜你喜欢

热点阅读