View的Touch事件分发流程

本文深入解析Android中View的Touch事件分发机制,包括事件链、事件消费等核心概念,以及dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent三个关键函数的处理流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概述

View的Touch事件分发大致分为两个过程:

  1. 从上向下的分发过程,调用的是dispatchTouchEvent()。
  2. 从下向上的处理过程,调用的是onTouchEvent()。

相关概念

Touch事件分发涉及到几个相关概念

事件链

这里涉及到事件链的概念,事件链是指从MotionEvent.ACTION_DOWN开始,到MotionEvent.ACTION_UP之间的一系列Touch事件,ACTION_DOWNACTION_UP之间可能没有其他事件,也可能包含ACTION_MOVEACTION_CANCELACTION_POINTER_DOWNACTION_POINTER_UP等。

事件消费

如果一个View对某个Touch事件感兴趣,并且它的onTouchEvent()返回了true,则称为该View消费了此次Touch事件。并且,一次Touch事件只会被一个View消费。事件消费与ACTION_DOWN联系紧密,在一个事件链中,只有消费了ACTION_DOWN事件的View才会有机会在onTouchEvent()中响应后续的事件。


详细流程

主要关心三个函数:

/* 从最顶层的ViewGroup开始调用,发起Touch事件的分发过程,返回true表示该ViewGroup处理了此次事件 */
boolean dispatchTouchEvent(MotionEvent ev);

/* 判断是否拦截此次Touch,返回true表示拦截,即不再将此次事件像子View传递 */
boolean onInterceptTouchEvent(MotionEvent ev);

/* 对Touch事件的处理业务,返回true表示消费此次事件 */
boolean onTouchEvent(MotionEvent ev);

处理流程:

  1. 所有事件链都是从ACTION_DOWN开始的,ViewGroup收到ACTION_DOWN后,会触发dispatchTouchEvent()发起分发过程。这会调用onInterceptTouchEvent(),如果后者返回值为false,即不拦截,则接下来依次调用子ViewdispatchTouchEvent()方法;如果返回值为true,则跳过遍历子View的步骤。
  2. 如果没有被拦截,dispatch会一直进行到最下面一层的View,然后沿着刚刚dispatch的顺序,反向依次调用各个ViewonTouchEvent();如果中途被拦截,即某个ViewdispatchTouchEvent()返回了false,则从拦截的View开始,沿着dispatch的顺序,反向依次调用各个ViewonTouchEvent()
  3. 依次调用onTouchEvent()的过程中, 如果某个ViewonTouchEvent()返回true,即该View对此次Touch事件感兴趣,则该View会被记录到此次事件链的mFirstTouch中,并且结束此次Touch事件的处理,不再继续调用父ViewonTouchEvent()。如果所有View的onTouchEvent()都返回了false,则结束事件处理时mFirstTouchnull
  4. 前面3步讲的都是ACTION_DOWN,下面开始处理事件链的后续Touch事件。当后续事件到来时(可能是除了ACTION_DOWN以外的任何事件),依然触发dispatchTouchEvent(),但处理逻辑不同,ViewGroup会判断mFirstTouchTarget是否为null,也就是判断以自己为根的View树中是否有人消费了之前的ACTION_DOWN,如果有人消费,则依次向下dispatch,直到找到消费了ACTION_DOWN事件的View,调用它的onTouchEvent()处理。如果没人消费,直接返回,结束此次分发。

参考文献

http://wugengxin.cn/download/pdf/android/PRE_andevcon_mastering-the-android-touch-system.pdf

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值