1 事件的传递顺序是 Activity -> Window -> 顶层View

touch 事件产生后,最先由 activity 的 dispatchTouchEvent 处理

  /**
* Called to process touch screen events. You can override this to
* intercept all touch screen events before they are dispatched to the
* window. Be sure to call this implementation for touch screen events
* that should be handled normally.
*
* @param ev The touch screen event.
*
* @return boolean Return true if this event was consumed.
*/
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
onUserInteraction();
}
if (getWindow().superDispatchTouchEvent(ev)) {
return true;
}
return onTouchEvent(ev);
}

接着事件会传到 Window 的 superDispatchTouchEvent。 如果所有的 view 都没有消费事件,最后会交给 activity 的 onTouchEvent 处理。

2 Window 是一个抽象类,它的唯一实现类是 PhoneWindow

/**
* Abstract base class for a top-level window look and behavior policy. An
* instance of this class should be used as the top-level view added to the
* window manager. It provides standard UI policies such as a background, title
* area, default key processing, etc.
*
* <p>The only existing implementation of this abstract class is
* android.view.PhoneWindow, which you should instantiate when needing a
* Window.
*/
public abstract class Window {
}

查看 PhoneWindow 的 superDispatchTouchEvent

public boolean superDispatchTouchEvent(MotionEvent event) {
return mDecor.superDispatchTouchEvent(event);
}

调用了 mDecor 的 superDispatchTouchEvent

private final class DecorView extends FrameLayout implements RootViewSurfaceTaker {}

// This is the top-level view of the window, containing the window decor.
private DecorView mDecor;

mDecor 就是 DecorView, DecorView 是一个 FrameLayout, 就是我们 setContentView 所设置 view 的父容器。

继续看 DecorView 的superDispatchTouchEvent

public boolean superDispatchTouchEvent(MotionEvent event) {
return super.dispatchTouchEvent(event);
}

调用了父类的 dispatchTouchEvent,  FrameLayout 中没有 dispatchTouchEvent, 实际上调用了 FrameLayout 的父类 ViewGroup 的 dispatchTouchEvent。

到此事件就传递到了顶层View(ViewGroup) 中,接着事件就从顶层 view 开始向子view分发。

3 事件分发主要涉及 3 个方法

public boolean dispatchTouchEvent(MotionEvent event)

事件传递到一个 view 时就会先调用这个 view 的 dispatchTouchEvent 进行往下分发

public boolean onInterceptTouchEvent(MotionEvent ev)

进行事件的拦截,只有 ViewGroup 有拦截方法, 单一View没有,事件传到 单一View 就直接调用 onTouchEvent 进行处理了

public boolean onTouchEvent(MotionEvent event)

处理事件,true 表示消费这个事件, false 表示不消费

4 下面的伪代码可以很好的说明事件的分发过程

public boolean dispatchTouchEvent(MotionEvent ev) {
boolean consume = false;
if (onInterceptTouchEvent(ev)) {
consume = onTouchEvent(ev);
}else {
consume = child.dispatchTouchEvent(ev);
} return consume;
}

事件传递到顶层 ViewGroup 中后, 就会调用 ViewGroup dispatchTouchEvent 进行分发。如果这个 ViewGroup 的 onInterceptTouchEvent 返回 true 表示它要拦截这个事件,接着就会调用它的 onTouchEvent 进行处理。如果不拦截则会交给它的子 view 继续进行分发, 如此反复直到事件被最终处理。

正常情况下,一个事件序列只能被一个 view 拦截且消耗。一个 view 一旦拦截了某个事件,那么同一个事件序列内的所有的事件都会交给它处理。

如果一个 view 的 onTouchEvent 返回 false, 那么它的父容器的 onTouchEvent 将会被调用,依次类推。如果所有的 view 都不处理这个事件,这个事件最后会返回到 activity 的 onTouchEvent 进行处理。

事件分发具体细节较为复杂,但基本流程就是上面的伪代码。事件分发机制是处理滑动冲突的根本,知道了原理,遇到问题再多看看源码就行了。

Android view 的事件分发机制的更多相关文章

  1. Android View的事件分发机制

    准备了一阵子,一直想写一篇事件分发的文章总结一下.这个知识点实在是太重要了. 一个应用的布局是丰富的,有TextView,ImageView,Button等.这些子View的外层还有ViewGroup ...

  2. Android View的事件分发机制和滑动冲突解决方案

    这篇文章会先讲Android中View的事件分发机制,然后再介绍Android滑动冲突的形成原因并给出解决方案.因水平有限,讲的不会太过深入,只希望各位看了之后对事件分发机制的流程有个大概的概念,并且 ...

  3. Android View的事件分发机制探索

    概述 Android事件传递机制也是Android系统中比较重要的一块,事件类型有很多种,这里主要讨论TouchEvent的事件在framework层的传递处理机制.因为对于App开发人员来说,理解f ...

  4. Android View 的事件分发原理解析

    作为一名 Android 开发者,每天接触最多的就是 View 了.Android View 虽然不是四大组件,但其并不比四大组件的地位低.而 View 的核心知识点事件分发机制则是不少刚入门同学的拦 ...

  5. 【Android - 自定义View】之View的事件分发机制

    参考资料: View事件分发:http://blog.csdn.net/pi9nc/article/details/9281829 ViewGroup事件分发:http://blog.csdn.net ...

  6. Android中的事件分发机制

    Android中的事件分发机制 作者:丁明祥 邮箱:2780087178@qq.com 这篇文章这周之内尽量写完 参考资料: Android事件分发机制完全解析,带你从源码的角度彻底理解(上) And ...

  7. View的事件分发机制解析

    引言 Android事件构成 在Android中,事件主要包含点按.长按.拖拽.滑动等,点按又包含单击和双击,另外还包含单指操作和多指操作.全部这些都构成了Android中的事件响应.总的来说.全部的 ...

  8. 浅谈Android中的事件分发机制

    View事件分发机制的本质就是就是MotionEvent事件的分发过程,即MotionEvent产生后是怎样在View之间传递及处理的. 首先介绍一下什么是MotionEvent.所谓MotionEv ...

  9. Android中View的事件分发机制

    简介 事件也称MotionEvent,事件分发机制就是对MotionEvent事件的分发过程,即当一个MotionEvent发生之后,系统需要把这个事件传递给一个具体的View. 点击事件的分发过程由 ...

随机推荐

  1. We are 歪果仁带你灰

    We are 歪果仁带你灰 我叫赖彦谕 不爱什么诗和远方 只爱饭桌上的一菜一肉一杯酒 真的很希望有一天我可以成为那个对待学习像对待美食一样的人类 让自己沉浸在美食和知识的海洋中无法自拔 我也对未来的软 ...

  2. [codeforces 241]C. Mirror Box

    [codeforces 241]C. Mirror Box 试题描述 Mirror Box is a name of a popular game in the Iranian National Am ...

  3. [BZOJ2502]清理雪道

    [BZOJ2502]清理雪道 试题描述 滑雪场坐落在FJ省西北部的若干座山上. 从空中鸟瞰,滑雪场可以看作一个有向无环图,每条弧代表一个斜坡(即雪道),弧的方向代表斜坡下降的方向. 你的团队负责每周定 ...

  4. 不用任何图片,只用简单的css写出唯美的钟表,就问你行吗?

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAgAAAAGHCAIAAABJR31QAAAgAElEQVR4nOy9aXhc1ZUurPvcH7f73n ...

  5. linux文件分割(将大的日志文件分割成小的)

    linux文件分割(将大的日志文件分割成小的) linux下文件分割可以通过split命令来实现,可以指定按行数分割和安大小分割两种模式.Linux下文件合并可以通过cat命令来实现,非常简单. 在L ...

  6. 动态设置Div坐标

    <style type="text/css"> #main{text-align:center; background-color:#9FF; height:600px ...

  7. java类的封装 继承 多态

    1.猜数字小游戏 package cn.jiemoxiaodi_02; import java.util.Scanner; /** * 猜数字小游戏 * * @author huli * */ pub ...

  8. c++ const总结

    [本文链接] http://www.cnblogs.com/hellogiser/p/cplusplus-const-summay.html 看到const 关键字,C++程序员首先想到的可能是con ...

  9. bat批量去除文件首行和合并到文件

    bat批量去除文件首行 set n=1 :starline for %%j in (*.txt) do ( :3 if exist D:\work\test\new_%n%.txt (set /a n ...

  10. php 301

    2013年7月1日 13:35:45 PHP在301跳转的时候,如果是跨域跳转,记着把要跳转到的URL添上"http://"