当前位置: 首页 > article >正文

Android事件分发:长按事件与双击事件的实现原理

本文同步发表于我的微信公众号微信搜索程语新视界即可关注每个工作日都有文章更新一、长按事件的源码实现长按事件的触发需要满足手指按下后持续一段时间默认500ms期间没有移动超过阈值期间没有抬起长按事件的核心实现在View.java中主要涉及以下几个关键方法// frameworks/base/core/java/android/view/View.java public class View { // 长按超时时间默认500ms private static final int LONG_PRESS_TIMEOUT 500; // 长按检查的延迟消息 private Runnable mPendingCheckForLongPress; // 触摸事件处理 public boolean onTouchEvent(MotionEvent event) { final int action event.getAction(); switch (action) { case MotionEvent.ACTION_DOWN: // 手指按下开始检测长按 if (!clickable) break; // 检查是否已经存在长按检测 if (mPendingCheckForLongPress null) { mPendingCheckForLongPress new CheckForLongPress(); } // 延迟500ms发送长按检测消息 postDelayed(mPendingCheckForLongPress, ViewConfiguration.getLongPressTimeout()); break; case MotionEvent.ACTION_MOVE: // 手指移动检查是否超出长按容忍范围 if (pointInView(x, y, mTouchSlop)) { // 在范围内继续保持长按检测 } else { // 移出范围移除长按检测 removeLongPressCallback(); } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: // 手指抬起或取消移除长按检测 removeLongPressCallback(); break; } } // 移除长按回调 private void removeLongPressCallback() { if (mPendingCheckForLongPress ! null) { removeCallbacks(mPendingCheckForLongPress); } } // 长按检测的Runnable实现 private final class CheckForLongPress implements Runnable { private int mOriginalWindowAttachCount; Override public void run() { if (isPressed() mParent ! null mOriginalWindowAttachCount mWindowAttachCount) { // 触发长按事件 if (performLongClick()) { // 长按消费了事件标记 mHasPerformedLongPress true; } } } } // 执行长按事件 public boolean performLongClick() { return performLongClickInternal(mLongClickX, mLongClickY); } private boolean performLongClickInternal(float x, float y) { // 1. 调用OnLongClickListener if (mOnLongClickListener ! null) { handled mOnLongClickListener.onLongClick(this); } // 2. 如果没有消费显示上下文菜单 if (!handled) { handled showContextMenu(x, y); } return handled; } }1.3 关键类ViewConfiguration// frameworks/base/core/java/android/view/ViewConfiguration.java public class ViewConfiguration { // 长按超时时间 private static final int LONG_PRESS_TIMEOUT 500; // 触摸移动的容差 private static final int TOUCH_SLOP 8; public static int getLongPressTimeout() { return LONG_PRESS_TIMEOUT; } public static int getTouchSlop() { return TOUCH_SLOP; } }1.4 长按事件的完整流程ACTION_DOWN ↓ postDelayed(CheckForLongPress, 500ms) ↓ 在此期间 - 如果移动超过阈值 → removeLongPressCallback - 如果手指抬起 → removeLongPressCallback - 如果手指未动 → CheckForLongPress.run() 在500ms后执行 ↓ performLongClick() ↓ mOnLongClickListener.onLongClick()二、双击事件的源码实现双击事件需要满足两次点击的间隔时间小于阈值默认300ms两次点击的位置距离小于阈值双击事件的核心实现在GestureDetector.java中// frameworks/base/core/java/android/view/GestureDetector.java public class GestureDetector { // 双击超时时间默认300ms private static final int DOUBLE_TAP_TIMEOUT 300; // 双击移动容差 private static final int DOUBLE_TAP_SLOP 100; // 双击检测的Handler private Handler mHandler; // 双击监听器 private OnDoubleTapListener mDoubleTapListener; // 当前手势状态 private int mCurrentDownEvent -1; private MotionEvent mPreviousUpEvent; // 触摸事件处理 public boolean onTouchEvent(MotionEvent ev) { final int action ev.getAction(); switch (action) { case MotionEvent.ACTION_DOWN: // 手指按下检查是否是双击 if (mDoubleTapListener ! null) { boolean hadTapMessage mHandler.hasMessages(TAP); if (hadTapMessage) { // 如果在TAP超时内再次按下可能是双击 if (isConsideredDoubleTap(mCurrentDownEvent, mPreviousUpEvent, ev)) { // 确实是双击 mStillDown true; mDeferConfirmSingleTap true; mInLongPress false; // 触发双击事件 mDoubleTapListener.onDoubleTap(ev); mDoubleTapListener.onDoubleTapEvent(ev); } } } break; case MotionEvent.ACTION_UP: // 手指抬起检查单击 if (mIsLongPress) { // 长按已经触发不处理单击 break; } if (mTapTimeout 0) { // 发送单击检测消息 mHandler.sendEmptyMessageDelayed(TAP, mTapTimeout); } break; } } // 判断是否是双击 private boolean isConsideredDoubleTap(MotionEvent firstDown, MotionEvent firstUp, MotionEvent secondDown) { if (!mAlwaysInTapRegion) { return false; } // 检查时间间隔 final long deltaTime secondDown.getEventTime() - firstUp.getEventTime(); if (deltaTime DOUBLE_TAP_TIMEOUT) { return false; // 时间太长不是双击 } // 检查位置偏移 int deltaX (int) firstDown.getX() - (int) secondDown.getX(); int deltaY (int) firstDown.getY() - (int) secondDown.getY(); if (deltaX * deltaX deltaY * deltaY DOUBLE_TAP_SLOP * DOUBLE_TAP_SLOP) { return false; // 位置变化太大不是双击 } return true; } // 单击检测的Handler private class GestureHandler extends Handler { Override public void handleMessage(Message msg) { switch (msg.what) { case TAP: if (mDoubleTapListener ! null !mStillDown) { // 触发单击事件如果没有双击的话 mDoubleTapListener.onSingleTapConfirmed(mCurrentDownEvent); } break; case LONG_PRESS: // 触发长按事件 dispatchLongPress(); break; } } } }2.3 关键类ViewConfiguration中的双击常量// frameworks/base/core/java/android/view/ViewConfiguration.java public class ViewConfiguration { // 双击超时时间 private static final int DOUBLE_TAP_TIMEOUT 300; // 双击移动容差 private static final int DOUBLE_TAP_SLOP 100; public static int getDoubleTapTimeout() { return DOUBLE_TAP_TIMEOUT; } public static int getDoubleTapSlop() { return DOUBLE_TAP_SLOP; } }2.4 双击事件的完整流程第一次ACTION_DOWN ↓ 第一次ACTION_UP ↓ postDelayed(TAP, 300ms) // 等待双击 ↓ 如果在300ms内发生第二次ACTION_DOWN ↓ isConsideredDoubleTap() 检查时间和位置 ↓ 如果是双击 → onDoubleTap() ↓ 取消TAP消息 ↓ 如果不是双击 → 触发单次点击确认实现原理事件实现方式超时时间判断条件长按Handler延迟消息500ms时间未移动未抬起双击两次点击的时间差300ms时间位置距离长按事件是通过Handler延迟500ms发送消息实现的双击事件是通过计算两次点击的时间差300ms和位置差100px实现的。

相关文章:

Android事件分发:长按事件与双击事件的实现原理

本文同步发表于我的微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新 一、长按事件的源码实现 长按事件的触发需要满足: 手指按下后持续一段时间(默认500ms) 期间没有移动超过阈值 期间没有抬起 …...

Qwen-Image-2512与LaTeX集成:学术论文图像生成

Qwen-Image-2512与LaTeX集成:学术论文图像生成 学术研究者每天需要为论文制作大量图表和示意图,传统绘图工具耗时耗力且专业门槛高 撰写学术论文时,图像质量往往直接影响研究成果的呈现效果。传统绘图工具如Photoshop或专业绘图软件需要大量学…...

嵌入式自定义通信协议设计与实现指南

1. 自定义协议设计原理与工程实践在嵌入式系统开发中,通信协议是连接不同功能模块的神经中枢。当标准协议(如Modbus、CANopen、HTTP)无法满足特定应用场景的轻量化、低开销或业务逻辑耦合需求时,自定义协议便成为工程师手中最灵活…...

计算机毕业设计springboot社区服务系统 基于SpringBoot的数字化社区综合服务管理平台 基于SpringBoot的社区便民信息服务系统

计算机毕业设计springboot社区服务系统gv80n9 (配套有源码 程序 mysql数据库 论文) 本套源码可以在文本联xi,先看具体系统功能演示视频领取,可分享源码参考。随着城市化进程加快和信息技术的发展,传统社区管理模式已难以满足居民多…...

避坑指南:Unity URP遮挡显示常见的5个问题及解决方案(含模板测试详解)

Unity URP遮挡显示实战:5大高频问题解析与深度优化方案 在Unity URP管线中实现遮挡显示效果,是许多3D项目提升视觉反馈的关键技术。无论是角色被墙壁遮挡时的轮廓高亮,还是特殊道具的透视效果,这一功能都能显著改善玩家体验。然而…...

VoxCPM-1.5-TTS模型Web界面部署:从安装到生成语音全记录

VoxCPM-1.5-TTS模型Web界面部署:从安装到生成语音全记录 1. 为什么选择VoxCPM-1.5-TTS 在当今AI语音合成领域,VoxCPM-1.5-TTS以其出色的音质和易用性脱颖而出。这个模型特别适合那些希望快速部署高质量语音合成系统,但又不想陷入复杂技术细…...

RMBG-2.0极速抠图:5分钟搞定透明背景PNG,小白也能轻松上手

RMBG-2.0极速抠图:5分钟搞定透明背景PNG,小白也能轻松上手 1. 为什么选择RMBG-2.0进行抠图? 在日常工作和设计中,我们经常需要处理图片背景去除的需求。无论是电商产品图、社交媒体配图还是设计素材,一个干净利落的透…...

打卡信奥刷题(2993)用C++实现信奥题 P6121 [USACO16OPEN] Closing the Farm G

P6121 [USACO16OPEN] Closing the Farm G 题目背景 本题和 银组同名题目 在题意上一致,唯一的不同是数据范围。 题目描述 FJ 和他的奶牛们正在计划离开小镇做一次长的旅行,同时 FJ 想临时地关掉他的农场以节省一些金钱。 这个农场一共有被用 MMM 条…...

RT-Thread在SF32LB52超低功耗MCU上的最小可运行工程

1. 项目概述“Hello HSPI”是一个面向黄山派(SiFli)SF32LB52系列超低功耗MCU的最小可运行验证工程,其核心目标并非实现复杂外设交互,而是建立一条端到端、可复现、可调试的嵌入式软件开发链路:从RT-Thread实时操作系统…...

Wan2.1 VAE赋能AIGC内容生产:自动化营销素材生成平台构建

Wan2.1 VAE赋能AIGC内容生产:自动化营销素材生成平台构建 1. 引言 想象一下,一个电商运营团队,每天需要为几十款新品制作社交媒体海报。设计师忙得焦头烂额,运营人员反复沟通修改,从创意到上线,一张图可能…...

Python实战:用奇异谱分析(SSA)给股票数据降噪,5步搞定时间序列预处理

Python实战:用奇异谱分析(SSA)给股票数据降噪,5步搞定时间序列预处理 金融数据分析师们每天面对海量股票数据时,最头疼的莫过于如何从市场噪音中识别出真实信号。去年我在分析某科技股季度波动时,发现传统移动平均方法会抹平重要转…...

Youtu-2B快速上手教程:WebUI交互界面部署详解

Youtu-2B快速上手教程:WebUI交互界面部署详解 想体验一个既轻快又聪明的AI对话助手吗?今天要介绍的Youtu-2B,就是一个能在普通电脑上流畅运行,还能帮你写代码、解数学题、创作文案的全能小帮手。它基于腾讯优图实验室开源的轻量化…...

丢失MSCOMCTL.OCX组件无法打开程序 教你免费修复方法

在使用电脑系统时经常会出现丢失找不到某些文件的情况,由于很多常用软件都是采用 Microsoft Visual Studio 编写的,所以这类软件的运行需要依赖微软Visual C运行库,比如像 QQ、迅雷、Adobe 软件等等,如果没有安装VC运行库或者安装…...

双模型策略:OpenClaw同时接入Qwen3-32B与Llama3的配置实战

双模型策略:OpenClaw同时接入Qwen3-32B与Llama3的配置实战 1. 为什么需要双模型策略? 去年我在尝试用OpenClaw自动化处理日常工作时,发现一个有趣的现象:简单的文件整理任务用轻量模型就能快速完成,但遇到需要复杂逻…...

e-Paper触控驱动库PDLS_EXT3_Basic_Touch解析与迁移指南

1. 项目概述PDLS_EXT3_Basic_Touch 是 Pervasive Displays 公司为其单色电子墨水屏(e-Paper Display, EPD)配套开发的嵌入式驱动库,专为搭载 EXT3.1 主控扩展板与 EXT3-Touch 触控扩展板的硬件平台设计。该库已正式进入废弃(Depre…...

用Matlab实现NGO - TCN - BiGRU - Attention多变量时间序列预测

Matlab完整源码和数据 1.基于NGO-TCN-BiGRU-Attention北方苍蝇算法优化时间卷积双向门控循环单元融合注意力机制多变量时间序列预测,要求Matlab2023版以上; 2.输入多个特征,输出单个变量,考虑历史特征的影响,多变量时间…...

2026年程序员效率翻倍实测:ChatGPT解决代码调试、文档生成等10大实际问题

在实际开发工作中,ChatGPT能显著提升效率:调试错误代码平均节省40%时间,生成单元测试可覆盖90%以上场景,技术文档撰写效率提升3倍。对于国内开发者而言,最便捷的免费体验方式是使用聚合平台RskAi(ai.rsk.cn…...

nlp_gte_sentence-embedding_chinese-large部署案例:政务公文自动分类向量化实践

nlp_gte_sentence-embedding_chinese-large部署案例:政务公文自动分类向量化实践 你是不是也遇到过这样的烦恼?每天面对堆积如山的政务公文,手动分类归档不仅耗时耗力,还容易出错。一份会议纪要、一份政策文件、一份请示报告&…...

基于Cocos2d-x元气骑士游戏

Soul Knight 项目说明文档 同济大学软件学院 2020 年面向对象程序设计课程大项目 项目信息 项目选题:元气骑士项目进度时间线: 游戏说明 游戏简介 元气骑士是一款地牢类角色扮演游戏,玩家将会在随机关卡中遇到不同的敌人,…...

别只盯着80端口:Tomato靶机渗透中那些容易被忽略的‘边路’突破口(2211端口与日志审计)

别只盯着80端口:Tomato靶机渗透中那些容易被忽略的‘边路’突破口 在渗透测试的世界里,80端口就像是一扇大门,吸引着大多数攻击者的目光。但真正的安全专家知道,真正的突破口往往藏在那些不起眼的角落。就像在Tomato靶机渗透中&am…...

FUTURE POLICE语音解构效果展示:多方言与嘈杂环境下的识别精度对比

FUTURE POLICE语音解构效果展示:多方言与嘈杂环境下的识别精度对比 今天咱们来聊聊一个挺有意思的语音技术——FUTURE POLICE的语音解构能力。你可能听说过不少语音识别工具,但大多数都是在安静环境下,对着标准普通话效果最好。一旦环境嘈杂…...

FPGA新手必看:用Vivado+ModelSim实现ADC128S022的SPI信号采集(附完整代码)

FPGA实战:基于Vivado与ModelSim的ADC128S022 SPI信号采集系统设计 第一次接触FPGA的SPI接口开发时,我被时序图和状态机搞得晕头转向。直到完成这个ADC128S022采集项目,才真正理解如何将理论转化为可运行的硬件逻辑。本文将分享从环境搭建到功…...

腾讯CodeBuddy.ai实战:5分钟用AI生成可部署的五子棋游戏(附房间系统源码)

腾讯CodeBuddy.ai实战:5分钟用AI生成可部署的五子棋游戏(附房间系统源码) 在快节奏的数字化时代,AI辅助开发正以前所未有的速度改变着编程工作流。本文将带您体验如何借助腾讯CodeBuddy.ai平台,仅用自然语言指令快速生…...

Kimi-VL-A3B-Thinking在科研场景的应用:论文图表理解与实验结果跨图对比分析

Kimi-VL-A3B-Thinking在科研场景的应用:论文图表理解与实验结果跨图对比分析 1. 科研场景中的多模态挑战 科研工作者每天需要处理大量论文图表和数据可视化内容。传统的人工分析方式存在三个主要痛点: 效率瓶颈:研究人员需要花费大量时间反…...

Whisper-large-v3企业级部署教程:Nginx反向代理+HTTPS安全访问完整配置

Whisper-large-v3企业级部署教程:Nginx反向代理HTTPS安全访问完整配置 1. 引言 如果你已经成功在本地跑通了Whisper-large-v3语音识别服务,那么恭喜你,你已经迈出了第一步。但要让这个服务真正能被团队或客户使用,本地访问是远远…...

OpenClaw实操指南01|发刊词:为什么要做一套能落地的OpenClaw实操系列

这是「OpenClaw 实操日更」的第 1 篇。目标只有一个:把"看起来很厉害"变成"你今天就能跑起来,并且明天还能稳定复现"。 这段时间,OpenClaw 的热度非常高。教程也很多,演示也很丝滑。 但我和很多朋友聊完后&am…...

从链表操作到内存管理:用5个C语言例子讲透结构体指针与双指针

从链表操作到内存管理:用5个C语言例子讲透结构体指针与双指针 在C语言开发中,结构体指针和双指针的运用是区分初级与中高级程序员的重要分水岭。许多开发者能够熟练使用基本指针操作,却在需要动态修改内存布局的复杂场景中频频踩坑。本文将通…...

Ragflow-main镜像下载卡住?5分钟搞定Docker国内加速配置

Ragflow-main镜像下载卡住?5分钟搞定Docker国内加速配置 最近在本地部署Ragflow时,不少开发者反馈ragflow-main镜像下载异常缓慢甚至完全卡住。这其实是Docker默认镜像源在国内访问不稳定的典型表现。今天我们就从原理到实操,彻底解决这个痛点…...

别再自己折腾服务器了!用腾讯视频插件5分钟搞定小程序视频播放功能

5分钟解锁小程序视频播放:腾讯视频插件全攻略 第一次在小程序里加视频时,我盯着服务器账单和审核驳回通知发呆了半小时。HTTPS证书、带宽峰值、类目审核…这些技术黑话像一堵高墙,把无数中小开发者挡在门外。直到发现腾讯视频插件——这个藏…...

17# 西门子 S7 - 200 PLC 与组态王打造自动贴标机控制系统

17#西门子S7-200PLC和组态王自动贴标机控制系统在工业自动化领域,自动贴标机的应用越来越广泛,而如何构建一个高效稳定的控制系统则是关键。今天就来聊聊利用西门子 S7 - 200 PLC 和组态王搭建的自动贴标机控制系统。 西门子 S7 - 200 PLC:核…...