Android的Touch事件处理机制介绍

 更新时间:2012年11月08日 16:33:33   作者:  
Android的Touch事件处理机制比较复杂,特别是在考虑了多点触摸以及事件拦截之后,有需求的朋友可以参考下
Android的Touch事件处理机制比较复杂,特别是在考虑了多点触摸以及事件拦截之后。
Android的Touch事件处理分3个层面:Activity层,ViewGroup层,View层。
首先说一下Touch事件处理的几条基本规则。
如果在某个层级没有处理ACTION_DOWN事件,那么该层就再也收不到后续的Touch事件了直到下一次ACTION_DOWN事件。

说明:
a.某个层级没有处理某个事件指的是它以及它的子View都没有处理该事件。
b.这条规则不适用于Activity层(它是顶层),它们可以收到每一个Touch事件。
c.如果没有处理ACTION_MOVE这类事件,不会有任何影响。

如果ACTION_DOWN事件发生在某个View的范围之内,则后续的ACTION_MOVE,ACTION_UP和ACTION_CANCEL等事件都将被发往该View,即使事件已经出界了。
第一根按下的手指触发ACTION_DOWN事件,之后按下的手指触发ACTION_POINTER_DOWN事件,中间起来的手指触发ACTION_POINTER_UP事件,最后起来的手指触发ACTION_UP事件(即使它不是触发ACTION_DOWN事件的那根手指)。

pointer id可以用于跟踪手指,从按下的那个时刻起pointer id生效,直至起来的那一刻失效,这之间维持不变。
如果一个ACTION_DOWN事件被父View拦截了,则任何子View不会再收到任何Touch事件了(这符合第1点的要求)。
如果一个非ACTION_DOWN事件被父View拦截了,则那些上次处理了ACTION_DOWN事件的子View会收到一个ACTION_CANCEL事件,之后不会再收到任何Touch事件了,即使父View不再拦截后续的Touch事件。

如果父View决定处理Touch事件或者子View没有处理Touch事件,则父View按照普通View的处理方式处理Touch事件,否则它根本不处理Touch事件(它只负责分发)。
如果父View在onInterceptTouchEvent中拦截了事件,则onInterceptTouchEvent中不会再收到Touch事件了,事件被直接交给它自己处理(按照普通View的处理方式)。
下面分层讲述一些细节。

1.Activity层:
复制代码 代码如下:

public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
onUserInteraction();
}
if (getWindow().superDispatchTouchEvent(ev)) { //在这里交给View层处理
return true;
}
return onTouchEvent(ev); // 如果View层没有处理,则在这里处理
}

2.View层:
复制代码 代码如下:

public boolean dispatchTouchEvent(MotionEvent event) {
// 省略了部分细节
ListenerInfo li = mListenerInfo;
if (li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
&& li.mOnTouchListener.onTouch(this, event)) {
return true;
}
if (onTouchEvent(event)) {
return true;
}
return false;
}

View的onTouch方法代码比较多,主要的逻辑分两步:先是将事件交给TouchDelegate处理(如果有的话),如果TouchDelegate没有处理再自行处理;自行处理主要负责View状态的变换(如按下状态),长按事件,点击事件的检测与触发等。

3.ViewGroup层(比较复杂):
ViewGroup层处理Touch事件的总体逻辑是:先检测是否需要拦截,没有拦截的话下发给子View处理,如果子View没有处理再自行处理,自行处理的逻辑与View一样。
拦截的逻辑是,将从down到up之间的所有事件看作一组事件,如果从down就拦截了,则组内的后续其它事件完全交给自己处理,不需要再进入拦截逻辑了;如果是从中间拦截,则先给子View发送cancel事件,组内的后续其它事件完全交给自己处理,不需要再进入拦截逻辑了。

分发的逻辑是,在ACTION_DOWN事件的时候,寻找子View进行处理,称为寻找Target;如果没有找到Target,则自行处理;如果找到Target,则交由Target处理。
从代码上看,dispatchTouchEvent负责分发逻辑,onTouchEvent负责真正的处理逻辑,一般应该重载onTouchEvent,只有特殊情况下才需要重载dispatchTouchEvent。

相关文章

  • Android利用Java优雅消除复杂条件表达式的方法

    Android利用Java优雅消除复杂条件表达式的方法

    这篇文章主要介绍了Android利用Java优雅消除复杂条件表达式,文章围绕主题展开详细的内容介绍,具有一定的参考价值。感兴趣的小伙伴可以参考一下
    2022-06-06
  • Android性能优化系列篇UI优化

    Android性能优化系列篇UI优化

    这篇文章主要为大家介绍了Android性能优化系列篇UI优化示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-10-10
  • 一文带你深入理解Android Window系统

    一文带你深入理解Android Window系统

    Android中的窗口系统是应用程序用户界面的核心组件之一,它负责管理可视化区域、处理用户输入事件以及与系统UI交互,本文将深入介绍与Android窗口系统相关的重要概念,需要的朋友可以参考下
    2023-10-10
  • Android运用BroadcastReceiver实现强制下线

    Android运用BroadcastReceiver实现强制下线

    本篇文章主要介绍了Android运用BroadcastReceiver实现强制下线,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-07-07
  • Android实现带页面切换的锁屏功能

    Android实现带页面切换的锁屏功能

    这篇文章主要为大家详细介绍了Android实现带页面切换的锁屏功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-06-06
  • 一文带你了解Android Flutter中Transform的使用

    一文带你了解Android Flutter中Transform的使用

    flutter的强大之处在于,可以对所有的widget进行Transform,因此可以做出非常酷炫的效果。本文就来大家了解一下Transform的具体使用,感兴趣的可以了解一下
    2023-01-01
  • 一文详解如何在Flutter中使用导航Navigator

    一文详解如何在Flutter中使用导航Navigator

    一个APP如果没有页面跳转那么是没有灵魂的,页面跳转的一个常用说法就是Navigator。那么在flutter中如何使用Navigator呢?本文就来和大家详细聊聊
    2023-02-02
  • Android自定义评分控件的完整实例

    Android自定义评分控件的完整实例

    在Android开发中,我们经常会用到对商家或者商品的评价,运用星星进行打分,下面这篇文章主要给大家介绍了关于Android自定义评分控件的相关资料,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2022-05-05
  • Android中使用OkHttp包处理HTTP的get和post请求的方法

    Android中使用OkHttp包处理HTTP的get和post请求的方法

    OkHttp包为安卓开发中的HTTP协议网络编程带来了很大的便利,这里我们就来看一下最基本的、Android中使用OkHttp包处理HTTP的get和post请求的方法:
    2016-07-07
  • Android EventBus(普通事件/粘性事件)详解

    Android EventBus(普通事件/粘性事件)详解

    这篇文章主要为大家详细介绍了Android EventBus 普通事件/粘性事件的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-11-11

最新评论