Android事件分发备忘

前言

事件的分发是面试的必考题,也是Android作为一个移动系统,与用户交互的基础。由于整个事件分发比较繁杂,这里做一个总结,以作备忘。

事实上,Android系统中的事件分发机制是一个委托者模型。我们先从最简单的看起。

三个方法

在Android的摸触事件中,我们通常关注的方法有三个。

dispatchTouchEvent(MotionEvent event)
onInterceptTouchEvent(MotionEvent event)
onTouchEvent(MotionEvent event)

这个三个方法组成了Android系统中,各个层级的事件分发,拉截和处理。


我们先从最熟悉的讲起:

View

View 作为视图层级中的最上层。是事件分发的终点

dispatchTouchEvent

View 的 作为最上层的控件,事件不再需要分发,因此,在dispatchTouchEvent中,几乎一定会调用 View 本身的 onTouchEvent(排除enable被关闭),同时将onTouchEvent的返回结果return。

onTouchEvent

在onTouchEvent中,Android实现了View的点击拖动等事件。

onInterceptTouchEvent

由于View 作为最上层视图不会再向更上层传递事件,所以没有onInterceptTouchEvent 方法。


ViewGroup

ViewGroup 作为视图层级中View的父控件。是事件分发的中间环节

dispatchTouchEvent

ViewGroup 的 作为中层的控件,不仅需要接收底层的事件(底层会调用ViewGroup的dispatchTouchEvent方法),还要将事件分发到上层,因此,在dispatchTouchEvent中,ViewGroup需要优先考虑onInterceptTouchEvent,如果事件被拦截,则直接调onTouchEvent,如果未被拦截,就需要调用所有子View的dispatchTouchEvent。

onTouchEvent

ViewGroup继承了View的onTouchEvent。有两种情况,ViewGroup的onTouchEvent方法会调用。

  1. ViewGroup的onInterceptTouchEvent返回true,表示ViewGroup决定拦截这个事件。
  2. ViewGroup的所有ChildView的onTouchEvent全部返回false,此时表示,没有任何一个ChildView愿意处理这个事件。所以,事件会返回给上层ViewGroup。同理,如果ViewGroup不处理这个事件,返回false,事件会继续往上传。
onInterceptTouchEvent
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        if (ev.isFromSource(InputDevice.SOURCE_MOUSE)
                && ev.getAction() == MotionEvent.ACTION_DOWN
                && ev.isButtonPressed(MotionEvent.BUTTON_PRIMARY)
                && isOnScrollbarThumb(ev.getX(), ev.getY())) {
            return true;
        }
        return false;
    }

返回true表拦截,false不拉截。

一图流:


看了上面的图,关于事件传递的所有疑惑应该都不存在了。接下来我们来探讨一下,事件分发的最上层是什么。

其实从上图中我们就可以看到,最上层的是Activity,Activity中有dispatchTouchEvent和onTouchEvent方法。因为Activity处于最上层,所以不存在拦截的问题。dispatchTouchEvent和onTouchEvent与ViewGroup的流程相同。


这里补充一点小小的信息。Activity与View的关系。同样是一图流:

以上。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏非著名程序员

AutoFlowLayout-多功能流式布局与网格布局控件

近期工作需要用到流式布局,网上也有很多关于这方面的资料。发现流式布局与网格布局的自定义很有意思,是学习自定义控件的一个很好的方式,所以就撸了个几百行代码的控件,...

29310
来自专栏Android先生

RecyclerView 梳理:点击&长按事件、分割线、拖曳排序、滑动删除

这次主要是把 RecyclerView 比较常用的基本的点,在这里集中整理一下。从这篇文章主要梳理以下几点:

953
来自专栏技术小黑屋

自定义View:Padding与绘制内容

有些时候,扩展Android框架提供的view并不能很好地解决问题。很多情况下,我们需要进行view绘制来实现想要的效果。本文我们将介绍如何使用Canvas绘制...

562
来自专栏分享达人秀

自定义ProgressBar打造酷炫进度条

Android系统默认的ProgressBar往往都不能满足实际开发需要,一般都会开发者自定义ProgressBar。 在Android开发中,...

6325
来自专栏分享达人秀

RecyclerView分割线开发技巧

在上一期通过简单学习,已经领略到了RecyclerView的灵活性,当然都是一些最基础的用法,那么本期一起来学习RecyclerView的分割线使用。 ...

2078
来自专栏Sorrower的专栏

动画必须有(二):悬浮菜单了解一下!

783
来自专栏androidBlog

自定义 Behavior - 仿新浪微博发现页的实现

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gdutxiaoxu/article/de...

551
来自专栏androidBlog

常用的自定义View例子一(流布式布局)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gdutxiaoxu/article/details/...

491
来自专栏CodingBlock

Android查缺补漏(View篇)--自定义 View 的基本流程

View是Android很重要的一部分,常用的View有Button、TextView、EditView、ListView、GridView、各种layout等...

33610
来自专栏编程思想之路

Activity加载view6.0源码分析---setContentView

本篇博文介绍三个方面的知识 chapter One:认识Activity的布局 chapter Two:启动activity时的布局--从setContent...

1868

扫码关注云+社区