事件分发机制

基本概述

需要关注下是View还是ViewGroup,但整体上是一致的。

事件分发机制主要解决的核心问题是,将Touch事件,传递 到 对应的view 来 消费:

  • 如何传递
  • 传递给谁

我们学习事件分发机制解决什么问题:

  • 如何利用机制去拦截目标事件
  • 如何利用机制去处理事件冲突

整体原则

  • 传递时,从外向内、从父到子
  • 消费时,从内向外、从子到父

三座大山

整个机制三个关键函数:

  • dispatchTouchEvent, 事件传递
    • 返回true,表明事件已经消费,会终止事件向下(由父向子)传递,结束
    • 返回false,表明事件未被消费,将会回传给父View的onTouchEvent
    • 调用super.dispatchTouchEvent,继续下传
  • onInterceptTouchEvent
    • 这个方法只存在于 ViewGroup 中
    • 返回true,表明要拦截事件,会回调onTouchEvent
    • 返回false,表明不做拦截,后面会继续下传
  • onTouchEvent, 事件消费
    • 返回true,表明事件被消费,结束
    • 返回false,表明事件没有被消费,将会继续回传父view
    • 调用super.onTouchEvent,继续往上回传

事件分发路径图

在默认的实现下,事件流向是一个U型图。

需要注意的是,

关键点

一般情况下,有以下事件:

  1. ACTION_DOWN
  2. ACTION_MOVE
  3. ACTION_UP
  4. ACTION_CANCEL

KEY 1

而我们说的一个事件就是指上面的某一个,但若说一个完整事件序列,则是从down--move--...--cancel/up这样一个所有一个操作周期所发生的所有事件。

KEY 2

不同的事件的分发路径其实是有所差别的。

一旦前面的事件确定了接收的view,那么分发的U形图就会"向上收缩"。 例如下图被ViewGroup2接收后,后续事件在默认情况下,如红线只会走到VG2然后被处理,蓝色区域不会走了。

KEY 3

CANCEL事件会稍微特殊一点,发生在后续事件被其他view拦截的时候,原来接收事件的view就会收到CANCEL事件。

例如,Down事件被下层消费之后,后续的Move、Up事件是有可能会被上层拦截的 。这也正是常常发生事件冲突的地方。

若被拦截,则原本应该消费的View会收到cancel事件。

滑动冲突的处理方式

滑动冲突是非常常见的,通常发生在多个可滑动的布局嵌套的场景,例如RecyclerView{ ScrollView }, RecyclerView{ ListView }, ViewPager{ RecyclerView }

典型的,根据两个控件的滑动方向,可以将滑动冲突分成两类:一个是不同方向的滑动冲突 ,如外层控件垂直滑动,内层控件水平滑动。另一个就是同方向的滑动冲突,如内外两层控件都是垂直滑动。

拦截方法有两种,本质也是万变不离其宗(改变分发的路线):

  • 外部拦截法
  • 内部拦截法

在一些特殊业务场景下,可能需要内外一起完成配合来实现特殊的效果。

(1)外部拦截法

在外层ViewGroup中的onInterceptTouchEvent中,对move事件进行精细化控制。

例如在外部是纵向、内部是横向的滚动场景时,我们判断dy>dx时【实际条件根据业务场景设置】选择拦截即在onInterceptTouchEvent中return true.

(2)内部拦截法

在内部ViewGroup中的dispatchTouchEvent或onTouchEvent方法中,调用api requestDisallowInterceptTouchEvent(true)来阻止父布局拦截后续事件。

这时候内部ViewGroup是不会回调onInterceptTouchEvent的,所以需要在dispatchTouchEvent或onTouchEvent方法中调用。

例如在外部是纵向、内部是横向的滚动场景时,我们判断dx>dy时【实际条件根据业务场景设置】

设置requestDisallowInterceptTouchEvent(true)

做滑动布局,应该在哪拦截事件?

首先滑动布局是ViewGroup类型,里面存在子View。

1)明确一点,滑动事件肯定是在ViewGroup层去拦截;

2)滑动事件拦截,不应该以Down为起点,而应该是MOVE。否则:子View的点击事件也会被拦截

3)Move事件应该在onInterceptTouchEvent中拦截

你可参考

juejin.cn/post/716844...

相关推荐
myaifas3 分钟前
新人的第一个任务该怎么选
前端·产品经理
怕浪猫14 分钟前
前端转全栈最低成本的技术栈选择
前端·javascript·面试
狂师16 分钟前
AI时代我们要如何玩抓包测试:Reqable + AI Agent
前端·程序员·测试
data analyse 45618 分钟前
页面卸载时埋点上报总丢失?sendBeacon 上报与补偿方案
大数据·运维·服务器·前端·数据库·人工智能·数据分析
WebInfra26 分钟前
Rsdoctor 2.0 发布:Agent 驱动的全自动优化工具
前端·javascript·node.js
乘风gg27 分钟前
AI Coding 时代最值钱的东西,软件工程(上)
前端·ai编程·claude
IT_陈寒34 分钟前
一文搞懂Vite的核心概念
前端·人工智能·后端
data analyse 45640 分钟前
前端白屏问题按路由和资源加载顺序定位
大数据·前端·人工智能·数据分析·html
mldong1 小时前
推荐一款支持AI的数据可视化一站式报表平台
前端·人工智能
风骏时光牛马1 小时前
AI开源工具一站式体验:上手探索原生AI能力
前端