Android自定义Viewandroid自定义view

android事件分发机制_具体的日志分析

2019-02-10  本文已影响39人  韩明泽

事件分发在android开发中是一个让人头疼的问题,也是在面试过程中问的比较多的一个问题。同样如果能了解事件分发的过程,将有利于我们处理在开发过程中遇到的组件间滑动问题。所以这个也是在复习的时候重点要看的知识点。在准备这篇文章资料的时候我也在草稿纸上画了几次流程,但是总感觉没有《图解 Android 事件分发机制》作者的流程图画的好,所以文章中的流程图就抄了这位作者的流程图(汗颜)。

项目源码

目录

image

1. 事件类型

当我们的手接触与屏幕接触得时候会产生一系列事件,我们可以通过MotionEvent这个类来得到事件的类型。常用的事件类型分为三种:

在正常的情况下,我们和手机交互会触发一些列的事件发生,例如点击事件会触发ACTION_DOWNN-->ACTION_MOVE,还有滑动事件会触发ACTION_DOWNN-->ACTION_MOVE-->ACTION_UP

2. 事件分发过程及顺序

事件分发过程: 事件的传递我们可以从点击事件来分析,点击事件触发后,系统把这个事件一层层分发,最终传递到具体的view中处理,这个事件的传递过程就是事件的分发过程。

事件的传递顺序是: Activity-->ViewGroup-->View

3. 分发的三个阶段

在研究事件分发的时候可结合上面的流程图

dispatchTouchEvent

分发事件阶段

这个事件可以分几种情况处理:

Activity中的处理

ViewGroup的处理

View中的处理

onInterceptTouchEvent

拦截事件,只有ViewGroup才有这个事件。

onTouchEvent

消耗事件阶段

这个事件也分下面几种情况处理

Activity中的处理

ViewGroup中的处理

View中的处理

4. 日志分析:

下面的所有日志信息可在GitHub的测试项目doc文件夹中的Android事件分发日志信息文件中查看到。

正常情况下日志信息(Activity、ViewGroup、View返回的都是父类同名方法)

View、ViewGroup以及Activity的onTouchEvent返回同名父类或者false的日志信息和下面的相同(Activity返回true也相同),所以就不在文章中粘出来了。

image

从上面的日志信息我们可以看到,当我们点击屏幕的个View的时候,事件先从EventActivity的dispatchTouchEvent分发给TestFrameLayout的dispatchTouchEvent然后在分发到TestView的dispatchTouchEvent中(提前是onInterceptTouchEvent没有拦截)最终交给了TestView的onTouchEvent方法。前文提到过,如果View的onTouch返回为false或者是父类的同名方法,将代表其不处理这个事件,那么事件将会回传。从上面的日志信息我们也能看出来,DOWN事件有被回传给TestFrameLayout的onTouchEvent处理。TestFrameLayout也是返回父类的同名方法,事件将继续回传最后回传到了EventActivity的onTouchEvent中吃力。另外我们从上面的信息中也可以看出,后面的UP事件也没有再向下分发,而是继续交给了Activity的onTouchEvent处理了。

View的onTouchEvent返回true的日志信息

当View的onTouch返回true的时候,代表要处理这个事件。这个事件就不会再回传,后续事件也将会交给他处理。可以分析下面红框的信息

image

当ViewGroup的onTouchEvent返回true时的日志信息

下面红色框为子控件日志信息,事件分发给ViewGroup的子组件TestView,但是它没有处理,事件回传给ViewGroup(黄色框中的日志),它的onTouchEvent返回true,代表事件被他消耗了,后续的事件也将分发给他处理。


image

当onInterceptTouchEvent返回true的日志信息

该方法如果返回为true,表示拦截,事件将交给TestFrameLayout自身的onTouchEvent处理(也就是最后事件消耗或者不消耗,都要看ViewGroup的onTouchEvent怎么处理了)。从下的日志信息中我们看到TestView的onTouchEvent方法并没有调用可以看出。


image

dispatchTouchEvent 返回true日志

注:下面给出的是ViewGroup的日志信息,View的该返回返回的信息和这个差不多,他们两个区别是View将事件传递给ViewGroup的dispatchTouchEvent,而ViewGroup将事件传递给的是Activity的dispatchTouchEvent方法中。因此由于篇幅原因,这里就粘出View的日志信息了。

如果dispatchTouchEvent返回true则代表事件被消耗,事件将不会在向下分发。后续事件将交给他处理。(View同理)


image

dispatchTouchEvent 返回false

如果dispatchTouchEvent返回false,事件也将不会在向下分发,事件将会回传给他上级的onTouchEvent方法中。后续事件将交给他的上级处理处理。(View同理)

image

终结

想要真正搞清楚事件分发,还是要亲自写个demo测试才能容易搞明白,这篇文章个人感觉写的还是有点乱(表达水平有限,嘿嘿)!如果看完了这篇文章不知道在说什么,可以看一看下面的两个链接,这两个链接算是我看过的讲事件分发的文章中写得计较好两个。推荐先看《图解 Android 事件分发机制》,一定要将作者画的流程图搞清楚。

参考:

图解 Android 事件分发机制

Android事件分发机制详解:史上最全面、最易懂

上一篇下一篇

猜你喜欢

热点阅读