您的位置:首页 > 移动开发 > Android开发

浅谈android 点击事件分发处理流程

2017-08-27 15:17 573 查看
在Android的事件处理过程中,经常会遇到需要拦截事件或者手动分发事件的情况,所以简单的了解一下Android的事件分发处理机制还是很有必要的。接下来, 借助一个简单的UI布局说明一下android的事件分发处理的工作流程!!

UI的简单的布局如图:



其中HELLO这个button为我们自定义的Button1,蓝色背景的布局为我们自定义的Group2,红色的为Group1。布局的xml如下所示:

<?xml version="1.0" encoding="utf-8"?>
<camera2.android.com.clickevent.Group1 xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorAccent">

<camera2.android.com.clickevent.Group2
android:layout_width="200dp"
android:layout_height="200dp"
android:background="@color/colorPrimaryDark">

<camera2.android.com.clickevent.Button1
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="hello" />
</camera2.android.com.clickevent.Group2>

</camera2.android.com.clickevent.Group1>


现在开始测试:

首先点击最外层的布局——Group1,打印的Log如下所示:

08-27 06:37:41.143 5428-5428/camera2.android.com.clickevent I/zyq: Group1-------onInterceptTouchEvent=false
08-27 06:37:41.143 5428-5428/camera2.android.com.clickevent I/zyq: Group1-------onTouchEvent=false
08-27 06:37:41.143 5428-5428/camera2.android.com.clickevent I/zyq: Group1-------dispatchTouchEvent=false


从log中可以看出,当我们点击一个view的时候,点击事件的分发和处理涉及到这三个方法:onInterceptTouchEvent、onTouchEvent、dispatchTouchEvent。

如果没有特殊的情况,这三个方法一般都是会走到的,而且在一个view中,当点击事件发生后,方法的执行顺序为:

onInterceptTouchEvent —>onTouchEvent—>dispatchTouchEvent

现在点击group2,打印的log如下:

08-27 06:37:56.085 5428-5428/camera2.android.com.clickevent I/zyq: Group1-------onInterceptTouchEvent=false
08-27 06:37:56.085 5428-5428/camera2.android.com.clickevent I/zyq: Group2-------onInterceptTouchEvent=false
08-27 06:37:56.085 5428-5428/camera2.android.com.clickevent I/zyq: Group2-------onTouchEvent=false
08-27 06:37:56.085 5428-5428/camera2.android.com.clickevent I/zyq: Group2-------dispatchTouchEvent=false
08-27 06:37:56.085 5428-5428/camera2.android.com.clickevent I/zyq: Group1-------onTouchEvent=false
08-27 06:37:56.085 5428-5428/camera2.android.com.clickevent I/zyq: Group1-------dispatchTouchEvent=false


根据log可以看出,首先捕捉到点击事件发生的View是最外层的UI,所以Group1有权决定是否将此次的点击事件中断,如果中断,将直接有Group1的onTouchEvent方法处理此次的点击事件,通过dispatchTouchEvent方发返回此次事件是否被消耗或者是否被分发成功等。

方法的执行流程为:

group1.onInterceptTouch—>group2.onInterceptTouch—>group2.onTouchEvent—>group2.dispatchTouchEvent—>group1.onTouchEvent—>group1.dispatchTouchEvent.

这是在事件没有任何处理的情况下会执行的流程,一旦事件被处理或者在onTouchEvent或者dispatchTouchEvent方法中返回true,那么都会表示这个事件已经被消耗,其外层的View将不会执行onTouchEvent方法,而是直接通过dispatchTouchEvent方法返回true,告诉其他相对外层的View事件已经被消耗!!

点击Button1,打印log如下:

ACTION_DOWN

08-27 06:38:51.301 5579-5579/camera2.android.com.clickevent I/zyq: Group1-------onInterceptTouchEvent=false
08-27 06:38:51.301 5579-5579/camera2.android.com.clickevent I/zyq: Group2-------onInterceptTouchEvent=false
08-27 06:38:51.303 5579-5579/camera2.android.com.clickevent I/zyq: Button1------onTouchEvent = true
08-27 06:38:51.303 5579-5579/camera2.android.com.clickevent I/zyq: Button1------dispatchTouchEvent = true
08-27 06:38:51.303 5579-5579/camera2.android.com.clickevent I/zyq: Group2-------dispatchTouchEvent=true
08-27 06:38:51.304 5579-5579/camera2.android.com.clickevent I/zyq: Group1-------dispatchTouchEvent=true

ACTION_UP
08-27 06:38:51.432 5579-5579/camera2.android.com.clickevent I/zyq: Group1-------onInterceptTouchEvent=false
08-27 06:38:51.432 5579-5579/camera2.android.com.clickevent I/zyq: Group2-------onInterceptTouchEvent=false
08-27 06:38:51.433 5579-5579/camera2.android.com.clickevent I/zyq: Button1------onTouchEvent = true
08-27 06:38:51.433 5579-5579/camera2.android.com.clickevent I/zyq: Button1------dispatchTouchEvent = true
08-27 06:38:51.433 5579-5579/camera2.android.com.clickevent I/zyq: Group2-------dispatchTouchEvent=true
08-27 06:38:51.433 5579-5579/camera2.android.com.clickevent I/zyq: Group1-------dispatchTouchEvent=true


点击了一下按钮,会执行两遍,这个就不多说了,看一下流程,基本与前面类似,但是由于Button1是继承至Button,可以有效的消耗用户的点击事件,所以group2和group1的onTouchEvent方法都没有执行,只是通过dispatchTouchEvent向相对外层的View说明事件的是否被消耗。

如果我们想要使得所有button点击事件都有Group2处理,不论group2能否正确处理都不能够将事件重新返回给Group1处理的话,我们可以选择使用事件拦截,首先在group2的onInterceptEvent方法中返回true,使得Group2拦截group2容器中的view点击事件,可以在group2的onTouchEvent或者dispatchTouchEvent方法中返回true,使其通知group1,这个事件已经被消耗,不需要group1在进行处理。

在没有事件拦截的情况下,最先执行的onTouchEvent方法的View肯定是用户点击的那个view。

关于Android的事件分发处理流程就说到这里,有兴趣的可以关注我一下,有什么问题可以相互讨论一下,谢谢!!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: