美文网首页面试Android知识Android开发
Android中的触屏事件分发机制

Android中的触屏事件分发机制

作者: gaaaaaaaaaao | 来源:发表于2016-10-19 22:07 被阅读141次

之前也自己学习过,但是当时学的不是很透彻而且有点忘了,重新总结一下。

首先,需要说一下,Android中的基本触屏事件主要有:按下、滑动、抬起。
分别对应的是MotionEvent类中的ACTION_DOWN,ACTION_MOVE,ACTION_UP。
而一个展示在我们面前的Activity大致有这么几层:
Activity -> PhoneWindow -> DecorView -> ViewGroup -> View
也就是说每个Activity都有一个Window对象,Window是一个抽象类,一般实现的是PhoneWindow,它会包含一个DecorView,这个就是整个窗口的根View,它其中的内容就是我们在布局文件中写的内容了。我们的布局文件都是在ViewGroup中包含一些控件,这就组成了一个Activity。
我们点击一下屏幕就产生一个事件,首先是最上层的Activity收到这个事件,它决定是否向下分发,我们一般操作的是从自定义ViewGroup开始的,因为在多控件重叠的时候如果处理不好点击事件的处理问题,就会导致一些控件无法响应。
事件的拦截与分发和处理主要由三个方法决定
顺序也是:分发-拦截-处理消费

  • dispatchTouchEvent
    事件分发,决定是否分发当前事件,如果不分发,也就表示事件到此之后不会往下走, 那就没有然后了。一般来讲不会改写这个方法,因为Activity、ViewGroup、View都有这个 方法,一旦不分发(返回true)结果只有一个,就是触屏事件没有消费者了,那么点击事件就等于没有了。
  • onInterceptTouchEvent(只有ViewGroup中才有这个方法)
    这个是一个很重要的方法,表示了是否拦截触屏事件。如果拦截,那么由于已经执行过事件分发,那这个事件就会传递到当前ViewGroup的onTouchEvent方法,由它进行事件处理,处理结束后返回上层的ViewGroup或Activity的onTouchEvent,其下层的View就没什么事了。如果不拦截,那么就会继续往下传递。
  • onTouchEvent
    一般在这个方法中处理触屏事件。处理完毕后默认向上返回。

下面通过一些例子来深刻认识一下,有一点要提的是,dispatchTouchEvent返回true表示消费了事件,就不进行分发;onInterceptTouchEvent返回true表示进行拦截,不继续传递;onTouchEvent返回true表示消费了事件,不用返回了。
首先是我的布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main3"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.gsq.viewtest01.Main3Activity">
    <com.example.gsq.viewtest01.viewgroup.ViewGroupTest01
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#ff0000" >
        <com.example.gsq.viewtest01.viewgroup.ViewGroupTest02
            android:layout_width="200dp"
            android:layout_height="200dp"
            android:background="#0000ff">
            <com.example.gsq.viewtest01.view.ViewTouchTest
                android:layout_width="100dp"
                android:layout_height="100dp"
                android:background="#00ff00" />
        </com.example.gsq.viewtest01.viewgroup.ViewGroupTest02>
    </com.example.gsq.viewtest01.viewgroup.ViewGroupTest01>
</RelativeLayout>

两个ViewGroup包了一个View。
大概这样:


Paste_Image.png

在默认的情况下,点击一下绿色区域(由于按下与抬起是两个事件,测试中只分析按下事件):


Paste_Image.png

这么来看的话,默认情况下,来一个事件,首先是dispatchTouchEvent进行分发,然后onInterceptTouchEvent判断是否拦截,不拦截就继续往下,也就是上层不断的往下层分发,一路不拦截,直到不能继续向下,然后最底层的View的onTouchEvent处理事件,再一路向上执行onTouchEvent。
如果ViewGroup1拦截了事件(onInterceptTouchEvent返回true):


Paste_Image.png
果然,分发了之后,进行拦截的话表示就不向下层继续传递了,那么就是当前ViewGroup1的onTouchEvent处理,处理结束后向上返回。

那如果在onTouchEvent中消费了事件呢?
将View中的onTouchEvent返回true:


Paste_Image.png

果然,onTouchEvent返回true,表示这个事件我消费完了,没了。
那么就不用再向上层传递了。同理,如果ViewGroup2的onTouchEvent返回true,那就表示ViewGroup2把事件消费了,事件没了,不用往上传了。

Paste_Image.png

上面的测试都是点击的绿色区域,当然了,如果点击的是蓝色区域,那么就是ViewGroup2在最底层,处理方式还是相同的。

后面自己自定义控件或布局重叠的时候遇到问题再回来补充。

相关文章

网友评论

本文标题:Android中的触屏事件分发机制

本文链接:https://www.haomeiwen.com/subject/ftoxuttx.html