因为最近因个人原因离职,面试的时候,有人问到了Android中事件分发机制的过程,因为忘得差不多了,没答好,所以回来后,想写了个Demo,重新复习一遍。

一般来说,Android的组件其实可以分为两类,即View和ViewGroup,而ViewGroup又继承于View。对于ViewGroup的是事件分发主要涉及到三个方法:

dispatchTouchEvent(MotionEvent ev),onInterceptTouchEvent(MotionEvent ev)和onTouchEvent(MotionEvent event),而View主要涉及到

dispatchTouchEvent(MotionEvent ev)和onTouchEvent(MotionEvent event)。顾名思义,dispatchTouchEvent用于分发Touch事件,

onInterceptTouchEvent用于拦截Touch事件,而onTouchEvent则是用于处理Touc事件。

首先,我们写一个简单的Demo来看看,

public class MyLinearLayout extends LinearLayout {

    public MyLinearLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
} public MyLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
} public MyLinearLayout(Context context) {
super(context);
} @Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.d("test", "MyLinearLayout"+" dispatchTouchEvent");
return super.dispatchTouchEvent(ev);
} @Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.d("test", "MyLinearLayout"+" onInterceptTouchEvent");
return super.onInterceptTouchEvent(ev);
} @Override
public boolean onTouchEvent(MotionEvent event) {
Log.d("test", "MyLinearLayout"+" onTouchEvent");
return super.onTouchEvent(event);
} }
public class MyView extends TextView {

    public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
} public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
} public MyView(Context context) {
super(context);
} @Override
public boolean dispatchTouchEvent(MotionEvent event) {
Log.d("test", "MyView"+" dispatchTouchEvent");
return super.dispatchTouchEvent(event);
} @Override
public boolean onTouchEvent(MotionEvent event) {
Log.d("test", "MyView"+" onTouchEvent");
return super.onTouchEvent(event);
} }
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.eventdemo.MainActivity" > <com.example.test1.MyLinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<com.example.test1.MyView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="00000000000000000000"
/> </com.example.test1.MyLinearLayout> </RelativeLayout>

上面我主要定义了一个ViewGroup(MyLinearLayout)和一个View(MyView),然后分别打印出dispatchTouchEvent(MotionEvent ev),onInterceptTouchEvent(MotionEvent ev)和onTouchEvent(MotionEvent event)的Log:

通过上面的Log可以看出,ViewGroup和View中的事件默认分发顺序是:ViewGruop.dispatchTouchEvent --> ViewGruop.onInterceptTouchEvent

--> View.dispatchTouchEvent --> View.onTouchEvent --> ViewGroup.onTouchEvent.

那如果我们对View的onTouchEvent事件的返回值修改下,会变成什么样呢?

首先,我将MyView中的onTouchEvent方法中直接return true,然后看下Log:

可以发现,MyLinearLayout的onTouchEvent没有执行,这是因为这次Touch事件已经被MyView消费了,即如果我们在方法中直接return true,那么事件就不会继续分发下去了。

接着,我们在MyLinearLayout的dispatchTouchEvent方法中return true,然后看Log:

总结如下:

  • dispatchTouchEvent返回true,意味后续不会将事件进行分发,而是直接在dispatchTouchEvent中进行拦截,即后续的ACTION_MOVE,ACTION_UP,ACTION_CANCEL事件只会触发ViewGroup和ViewGroup之前路径的View以及ViewGroup(需要注意的是,如果是在onTouch中,返回true,则下次的ACTION_DOWN,ACTION_UP就只会触发该ViewGroup的onTouch事件,即系统是会记住消费了onTouch事件的那个ViewGroup来传递事件)的dispatchTouchEvent和onInterceptTouchEvent
    ,而不会触发ViewGroup以及ViewGroup之后的View的onInterceptTouchEvent()和onTouchEvent()事件.
  • dispatchTouchEvent返回返回false,意味着不处理该事件,也不往下分发事件。即后续不会收到ACTION_MOVE,ACTION_UP,ACTION_CANCEL事件.
  • 返回super.dispatchTouchEvent(ev)意味着不处理该事件,而是依次向子View分发该事件,直到找到需要消费本次事件的View.

所以如果我们需要将事件拦截下来的话,直接return true就可以了。

Anroid事件分发的更多相关文章

  1. C++中的事件分发

    本文意在展现一个C++实现的通用事件分发系统,能够灵活的处理各种事件.对于事件处理函数的注册,希望既能注册到普通函数,注册到事件处理类,也能注册到任意类的成员函数.这样在游戏客户端的逻辑处理中,可以非 ...

  2. Android事件分发机制浅谈(一)

    ---恢复内容开始--- 一.是什么 我们首先要了解什么是事件分发,通俗的讲就是,当一个触摸事件发生的时候,从一个窗口到一个视图,再到一个视图,直至被消费的过程. 二.做什么 在深入学习android ...

  3. 简单例子了解View的事件分发

    什么是事件分发 我们在写自定义ViewGroup或者自定义View的时候经常要处理用户的点击事件,如果我们的View在最底层,他在很多ViewGroup里面,我们如何让我们的点击事件准确传递到View ...

  4. Android事件分发机制浅谈(二)--源码分析(ViewGroup篇)

    上节我们大致了解了事件分发机制的内容,大概流程,这一节来分析下事件分发的源代码. 我们先来分析ViewGroup中dispatchTouchEvent()中的源码 public boolean dis ...

  5. 通俗理解Android事件分发与消费机制

    深入:Android Touch事件传递机制全面解析(从WMS到View树) 通俗理解Android事件分发与消费机制 说起Android滑动冲突,是个很常见的场景,比如SliddingMenu与Li ...

  6. EventDispatcher 事件分发组件

    引言 考虑这样一个问题,现在你想给为你的项目提供一个插件系统,插件可以添加一些方法,或者在某些方法执行之前或者之后做些事情,而不干扰其他插件.要实现这个系统,简单的单继承不是个好办法,即使多继承在PH ...

  7. Android事件分发小结

      ******** ******** 第一部分: 介绍说明 ******** ********        个人感觉在做交互的时候, 对于Android的按键分发的理解还是比较重要的. 这些内容在 ...

  8. Atitit View事件分发机制

    1. Atitit View事件分发机制 1. Atitit View事件分发机制1 1.1. 三个关键方法 dispatchTouchEvent onInterceptTouchEvent onTo ...

  9. [DOM Event Learning] Section 4 事件分发和DOM事件流

    [DOM Event Learning] Section 4 事件分发和DOM事件流 事件分发机制: event dispatch mechanism. 事件流(event flow)描述了事件对象在 ...

随机推荐

  1. WEB接口测试之Jmeter接口测试自动化 (三)(数据驱动测试)

     接口测试与数据驱动 1简介 数据驱动测试,即是分离测试逻辑与测试数据,通过如excel表格的形式来保存测试数据,用测试脚本读取并执行测试的过程. 2 数据驱动与jmeter接口测试 我们已经简单介绍 ...

  2. oracle 树查询

    select LPAD('-----',t.menu_level)||t.obj_id,t.*,rowid from imes10dba.tb_adm_menu t start with t.pare ...

  3. 实时竞价RTB广告平台_传漾科技_中国领先的智能数字营销引擎

    实时竞价RTB广告平台_传漾科技_中国领先的智能数字营销引擎 Programmatic Framework™ 传漾程序化购买框架

  4. Linux 嵌入式启动以及优化

    转载:http://www.embeddedlinux.org.cn/html/jishuzixun/201312/19-2717.html 第一步: BootLoader -- U boot   1 ...

  5. 【Linxu】CentOS7下安装程序报错:

    进入root用户,然后编辑 vi /usr/libexec/urlgrabber-ext-down 将首行换成 #!/usr/bin/python2.

  6. Linux如何显示文件指定行数的内容;显示第一行、中间几行和最后几行

    1.tail -n +/-数字 文件名 2.head -n 数字 文件名 3.sed -n "开始行,结束行p" 文件名 4.sed -n '1p;20,40p; "显示 ...

  7. TDDL-剖析淘宝TDDL

    TDDL-剖析淘宝TDDL 学习了:https://blog.csdn.net/sumj7011/article/details/78286741 Taobao Distribute Data Lay ...

  8. Objective C block背后的黑魔法

    前言 block在Objective C开发中应用非常广泛,我们知道block会捕获外部对象,也知道使用block要防止循环引用. "知其然而不知其所以然"是一件非常痛苦的事情,那 ...

  9. 如何在微信小程序中使用字体图标

    微信小程序中,在image标签里,可以在src中引用本地文件,但是background设置背景图或者使用字体图标的时候,却不能引用本地文件,只能用url地址的图片或字体,或者使用base64编码后的格 ...

  10. C#注冊表操作汇总

    一.注冊表基本知识 1)       结构 键->项->子项->值项(名称.类型.数据) REG_SZ         字符串 REG_BINARY    二进制 REG_DWORD ...