Android View 事件分发机制,看这一篇就够了(一)

简介: Android View 事件分发机制,看这一篇就够了

在 Android 开发当中,View 的事件分发机制是一块很重要的知识。不仅在开发当中经常需要用到,面试的时候也经常被问到。


如果你在面试的时候,能把这块讲清楚,对于校招生或者实习生来说,算是一块不错的加分项。对于工作几年的我们来说,这是必须掌握的,讲不明白,那你回去等通知吧,哈哈。


目录大概如下:


  1. View 事件分发机制简介
  2. View 常见滑动冲突解决
  3. View 双击,多击事件是怎么实现的
  4. 手势识别
  5. 小结


View 事件分发机制简介


View 触摸事件


对于屏幕的点击,滑动,抬起等一系的动作,其实都是由一个一个MotionEvent对象组成的。根据不同动作,主要有以下三种事件类型:


  1. ACTION_DOWN:手指刚接触屏幕,按下去的那一瞬间产生该事件
  2. ACTION_MOVE:手指在屏幕上移动时候产生该事件
  3. ACTION_UP:手指从屏幕上松开的瞬间产生该事件
  4. ACTION_CANCEL 当前 View 的手势被打断,后续不会再收到任何事件


从 ACTION_DOWN 开始到 ACTION_UP/ACTION_CANCEL 结束我们称为一个事件序列


正常情况下,无论你手指在屏幕上有多么骚的操作,最终呈现在 MotionEvent 上来讲无外乎下面 3 种 case。


  1. 点击后抬起,也就是单击操作:ACTION_DOWN -> ACTION_UP
  2. 点击后再风骚的滑动一段距离,再抬起:ACTION_DOWN -> ACTION_MOVE -> … -> ACTION_MOVE -> ACTION_UP
  3. 某些情况下,我们可能会没有收到 ACTION_UP 事件,是收到 ACTION_CANCEL 事件。


ACTION_CANCEL 一般是指 ChildView 原先拥有事件处理权,后面由于某些原因,该处理权需要交回给上层去处理,ChildView便会收到 ACTION_CANCEL 事件。对于一些复位或者重置操作,我们应该在 ACTION_UP 和 ACTION_CANCEL 里面同时进行处理。


代码逻辑上是:上层判断之前交给ChildView的事件处理权需要收回来了,便会做事件的拦截处理,拦截时给ChildView发一个ACTION_CANCEL事件


几个主要方法


我们知道,View 的事件分发机制主要涉及到以下几个方法


  • dispatchTouchEvent ,这个方法主要是用来分发事件的
  • onInterceptTouchEvent,这个方法主要是用来拦截事件的(需要注意的是 ViewGroup 才有这个方法,View 没有 onInterceptTouchEvent 这个方法)
  • onTouchEvent 这个方法主要是用来处理事件的
  • requestDisallowInterceptTouchEvent(true),这个方法能够影响父View是否拦截事件,true 表示父 View 不拦截事件,false 表示父 View 拦截事件


我们先来看一张图。


以下内容参考图解 Android 事件分发机制这一篇博客


841411e3942719f0c8d699b000b7c36f_60464b2b95c3b27283e0d1191d93390d.png


  • 仔细看的话,图分为3层,从上往下依次是Activity、ViewGroup、View
  • 事件从左上角那个白色箭头开始,由 Activity 的 dispatchTouchEvent 进行分发
  • 箭头的上面字代表方法返回值,(return true、return false、return super.xxxxx(),super 的意思是调用父类实现。)
  • dispatchTouchEvent和 onTouchEvent的框里有个【true---->消费】的字,表示的意思是如果方法返回true,那么代表事件就此消费,不会继续往别的地方传了,事件终止。
  • 目前所有的图的事件是针对ACTION_DOWN的,对于ACTION_MOVE和ACTION_UP我们最后做分析。


当触摸事件发生时,首先 Activity 将 TouchEvent 传递给最顶层的 View,TouchEvent最先到达最顶层 view 的 dispatchTouchEvent ,然后由 dispatchTouchEvent 方法进行分发,


如果dispatchTouchEvent返回true 消费事件,事件终结。


如果dispatchTouchEvent返回 false ,则回传给父View的onTouchEvent事件处理;


如果dispatchTouchEvent返回super的话,默认会调用自己的onInterceptTouchEvent方法。


  • 默认的情况下onInterceptTouchEvent回调用super方法,super方法默认返回false,所以会交给子View的onDispatchTouchEvent方法处理
  • 如果 interceptTouchEvent 返回 true ,也就是拦截掉了,则交给它的 onTouchEvent 来处理,
  • 如果 interceptTouchEvent 返回 false ,那么就传递给子 view ,由子 view 的 dispatchTouchEvent 再来开始这个事件的分发。


关于更多详细分析,请查看原博客图解 Android 事件分发机制,真心推荐,写得很好。


View 滑动事件冲突


在开发当中,View 的滑动冲突时经常遇到的,比如 ViewPager 嵌套 ViewPager,ScrollView 嵌套 ViewPager。下面让我们一起来看看怎么解决。


常见的三种情况


第一种情况,滑动方向不同


32c518544cb4bf581055d83d35c432ea_2a8ca442460adf8bb4349ae8cc58a4c0.jpeg


第二种情况,滑动方向相同


c4e4833236eb8752be939571a45a6dac_3e5a4ccf4b230ee6e96303b787f41fae.jpeg


第三种情况,上述两种情况的嵌套


ea6d9e5ecbb182542d6982eda563e7f2_bb08d8128210f9690aad4cefecf81060.png


解决思路


看了上面三种情况,我们知道他们的共同特点是父View 和子View都想争着响应我们的触摸事件,但遗憾的是我们的触摸事件 同一时刻只能被某一个View或者ViewGroup拦截消费,所以就产生了滑动冲突。


那既然同一时刻只能由某一个 View 或者 ViewGroup 消费拦截,那我们就只需要 决定在某个时刻由这个 View 或者 ViewGroup 拦截事件,另外的 某个时刻由 另外一个 View 或者 ViewGroup 拦截事件,不就 OK了吗?


综上,正如 在 《Android开发艺术》 一书提出的,总共 有两种解决方案


以下解决思路来自于 《Android开发艺术》 书籍


下面的两种方法针对第一种情况(滑动方向不同),父View是上下滑动,子View是左右滑动的情况。


相关文章
|
22天前
|
缓存 测试技术 Android开发
深入探究Android中的自定义View绘制优化策略
【4月更文挑战第8天】 在Android开发实践中,自定义View的绘制性能至关重要,尤其是当涉及到复杂图形和动画时。本文将探讨几种提高自定义View绘制效率的策略,包括合理使用硬件加速、减少不必要的绘制区域以及利用缓存机制等。这些方法不仅能改善用户体验,还能提升应用的整体性能表现。通过实例分析和性能测试结果,我们将展示如何有效地实现这些优化措施,并为开发者提供实用的技术指南。
|
27天前
|
前端开发 Android开发 开发者
深入探究Android中的自定义View组件开发
【4月更文挑战第3天】 在现代Android应用程序的开发过程中,创建具有独特功能和高度定制化的用户界面是一个常见需求。为此,理解并掌握自定义View组件的开发成为了开发者必备的技能之一。本文将深入探讨如何在Android中创建自定义View,从基础的绘制原理到事件处理机制,再到性能优化技巧,旨在为读者提供一个全面的技术视角,并通过实例代码演示如何实现一个功能丰富、响应迅速的自定义View组件。
|
28天前
|
前端开发 编译器 Android开发
构建高效Android应用:探究Kotlin协程的异步处理机制
【4月更文挑战第2天】在现代移动应用开发中,提供流畅且响应迅速的用户体验是至关重要的。随着Android平台的发展,Kotlin语言凭借其简洁性和功能性编程的特点成为了主流选择之一。特别地,Kotlin协程作为一种新型的轻量级线程管理机制,为开发者提供了强大的异步处理能力,从而显著提升了应用程序的性能和响应速度。本文将深入探讨Kotlin协程在Android中的应用,分析其原理、实现以及如何通过协程优化应用性能。
|
4月前
|
Android开发 容器
Android UI设计: 什么是View和ViewGroup?
Android UI设计: 什么是View和ViewGroup?
36 0
|
4月前
|
存储 Java Android开发
Android系统升级的机制概要
Android系统升级的机制概要
44 0
|
18天前
|
XML 数据可视化 Android开发
深入探究Android中的自定义View组件开发
【4月更文挑战第12天】在安卓应用开发中,创建具有独特交互和视觉表现的自定义View组件是增强用户体验的重要手段。本文将详细阐述如何从头开始构建一个Android自定义View,包括理解View的工作原理、处理绘制流程、事件分发机制以及属性的自定义与管理。通过具体案例分析,我们将一步步实现一个可定制的动态进度条,不仅具备基础功能,还能根据业务需求进行扩展,体现高度的产品个性化。
|
22天前
|
XML Java Android开发
Android控件之基础控件——进度条类的view——TextView、Checkbox复选控件、RadioButton单选控件、ToggleButton开关、SeekBar拖动条、menu、弹窗
Android控件之基础控件——进度条类的view——TextView、Checkbox复选控件、RadioButton单选控件、ToggleButton开关、SeekBar拖动条、menu、弹窗
|
28天前
|
前端开发 Android开发 容器
Android View介绍
Android View介绍
20 0
|
28天前
|
API 调度 Android开发
探索Android应用程序的后台运行机制
在移动应用开发中,了解和掌握Android应用程序的后台运行机制至关重要。本文将深入探讨Android平台上应用程序的后台运行原理及其影响因素,包括后台服务、广播接收器、JobScheduler等关键组件,以及如何有效管理后台任务以提升应用性能和用户体验。
16 3
|
5月前
|
XML API Android开发
Android 自定义View 之 Dialog弹窗
Android 自定义View 之 Dialog弹窗