资讯动态

expo-haptics 跨平台触觉反馈模块解析:从 CHANGELOG 看 API 演进与三端实现原理

发布时间:2026/9/10 21:03:02 来源:尧图企业网站定制
expo-haptics 跨平台触觉反馈模块解析从 CHANGELOG 看 API 演进与三端实现原理【免费下载链接】expoAn open-source framework for making universal native apps with React. Expo runs on Android, iOS, and the web.项目地址: https://gitcode.com/GitHub_Trending/ex/expoexpo-haptics 是 Expo 生态中用于向用户提供系统级触觉反馈Haptics的官方模块在 iOS 上调用系统触觉引擎、在 Android 上触发振动效果、在 Web 端对接 Web Vibration API。本文以 packages/expo-haptics/CHANGELOG.md 为主线结合当前仓库源码梳理该模块的版本演进、公开 API 全貌、三端底层实现差异以及升级过程中值得关注的破坏性变更帮助开发者在自己的 Expo / React Native 项目中正确选型与使用触觉反馈能力。模块概览一套 API三端反馈根据 packages/expo-haptics/package.json 的描述expo-haptics 提供的是iOS 系统触觉引擎、Android 振动效果、Web Vibration API的统一封装。当前仓库内模块的最新版本为 57.0.1其目录结构如下src/Haptics.ts对外导出的 JS/TS 入口定义全部异步 APIsrc/Haptics.types.ts公开枚举与类型定义src/ExpoHaptics.web.tsWeb 平台实现ios/HapticsModule.swiftiOS 原生实现android/src/main/java/expo/modules/haptics/HapticsModule.ktAndroid 原生实现。调用方式非常简单安装后直接导入即可使用npx expo install expo-haptics在 managed Expo 项目中上述命令会自动安装匹配当前 SDK 版本的依赖在 bare React Native 项目中需要先确保已安装并配置好expo包安装后 iOS 侧还需执行npx pod-install。Android 侧所需的android.permission.VIBRATE振动权限已由模块自动声明见 android/src/main/AndroidManifest.xml无需手动配置——这一点在 packages/expo-haptics/README.md 中有明确说明。公开 API 全景四种反馈类型当前版本对外暴露了四个异步函数均返回Promisevoid源码见 src/Haptics.ts1. notificationAsync(type)用于通知类反馈参数为NotificationFeedbackType默认Success。在 iOS 上直接映射到UINotificationFeedbackGeneratorAndroid 上则用Vibrator模拟。枚举定义见 src/Haptics.types.tsSuccess成功完成某任务Warning任务产生警告Error任务失败2. impactAsync(style)模拟物理碰撞的冲击反馈参数为ImpactFeedbackStyle默认Medium。iOS 上直接映射UIImpactFeedbackGenerator.FeedbackStyleAndroid 上同样用Vibrator模拟。注意ImpactFeedbackStyle共有五个取值Light、Medium、Heavy、Rigid、Soft。其中rigid与soft是 13.0.0 版本才引入的新类型见 CHANGELOG 13.0.0 条目对应刚性碰撞压缩量小与柔性碰撞压缩量大两种手感。3. selectionAsync()用于选中状态变化的轻反馈无参数在 iOS 上对应UISelectionFeedbackGeneratorAndroid 上以Vibrator模拟。4. performAndroidHapticsAsync(type)Android 专属这是 14.1.0 版本新增的 Android 专属方法参数为AndroidHaptics枚举见 src/Haptics.ts。它走的是View.performHapticFeedback()系统通道不依赖也不推荐VibratorAPI并且不需要VIBRATE权限。源码注释明确建议需要实现类似 iOS 手感的反馈时应优先使用该方法。AndroidHaptics枚举定义于 src/Haptics.types.ts共 20 个取值覆盖了 Android 系统内置的各类场景化反馈例如Confirm/Reject确认成功 / 拒绝失败Gesture_Start/Gesture_End手势开始如软键盘/ 手势结束Toggle_On/Toggle_Off开关切换Keyboard_Tap/Keyboard_Press/Keyboard_Release软键盘按键Long_Press、Context_Click、Virtual_Key、Clock_Tick、Text_Handle_Move等Segment_Tick/Segment_Frequent_Tick选择项切换后者要求极轻连续触发也不能造成不适硬件无法给出足够轻柔的振动时允许不振动No_Haptics明确不触发任何反馈需要注意的是performAndroidHapticsAsync内部会先判断Platform.OS ! android并直接返回因此非 Android 平台调用它是安全无副作用的。版本演进史CHANGELOG 里的关键节点CHANGELOG 完整记录了从 8.2.02020-05到 57.0.12026-07的历次发布。其中大量版本标注为This version does not introduce any user-facing changes.真正有实质变化的关键节点如下。尚未发布Unpublished的修复当前未发布版本中包含一条 Android 修复[android] Fix performAndroidHapticsAsync doing nothing by running it on the main queue.#49263结合 HapticsModule.kt 的源码注释可以理解其根因View.performHapticFeedback是**主线程亲和main-thread affine**的 API而AsyncFunction默认运行在模块调度器modules dispatcher所在的非主线程上此时调用会静默地什么都不做其他函数使用线程安全的Vibrator因此只有该方法需要显式指定Queues.MAINAsyncFunction(performHapticsAsync) { type: HapticType - val view appContext.currentActivity?.findViewByIdView(android.R.id.content) view?.performHapticFeedback(type.toHapticFeedbackType()) }.runOnQueue(Queues.MAIN)这条修复与 55.0.0 中的另一条修复Fix missing await for performHapticsAsync呼应说明 Android 专属通道在权限简化无需VIBRATE的同时也经历了多次针对调度与异步语义的打磨。56.0.0Apple 平台最低版本提升破坏性变更Bumped minimum iOS/tvOS version to 16.4, macOS to 13.4.从 56.0.0 起expo-haptics 要求 iOS/tvOS ≥ 16.4、macOS ≥ 13.4。回顾历史可以看出一条清晰的平台基线提升轨迹9.0.02021-01放弃 iOS 1011.0.02021-09放弃 iOS 1112.0.02022-10iOS 部署目标提升至 13.0放弃 iOS 1212.8.02023-11iOS 部署目标提升至 13.414.0.02024-10iOS 部署目标提升至 15.156.0.02026-05iOS/tvOS 16.4、macOS 13.4。如果你的应用仍需支持旧系统应锁定使用较早版本的 expo-haptics。55.0.12iOS Safari 的 Web 端反馈Add web haptics for iOS Safari using checkbox.这是 Web 实现的关键补强。iOS Safari 不支持navigator.vibrate但通过一个隐藏的input typecheckbox switch元素并程序化触发click()可以借用系统对开关切换的原生触觉反馈见 src/ExpoHaptics.web.ts。这是该模块 Web 端降级但不缺席策略的一部分。14.1.0Android 新时代与 Web 支持起点[Android] Added new method performAndroidHapticsAsync(). The Vibrator api is no longer recommended.[Web] Add web support using Web Vibration API.14.1.0 是功能最丰富的一次发布确立了当前的三端形态Android 迎来不依赖Vibrator的新通道Web 首次接入 Web Vibration API同时 Android 构建切换到 expo modules gradle pluginApple 侧统一了expo-module.config.json的平台语法。13.0.0新增 rigid / soft 冲击类型Introducerigidandsoftimpact types.这是ImpactFeedbackStyle从 3 值扩为 5 值的里程碑让 iOS 与 Android 都能表达更细腻的碰撞手感。12.8.0Android 振幅与时长优化Improve Android vibration amplitudes and durations.从 HapticsImpactType.kt 可以看出Android 侧每种冲击类型都定义了现代API 26使用VibrationEffect.createWaveform(timings, amplitudes, -1)与旧 SDKoldSDKPattern两套振动参数类型timings现代amplitudes现代oldSDKPatternlight / soft[0, 50][0, 30][0, 20]medium / rigid[0, 43][0, 50][0, 43]heavy[0, 60][0, 70][0, 61]同一类型的 light/soft、medium/rigid 在现代参数上保持一致说明 Android 侧力度主要由振幅30/50/70区分而 iOS 侧则由系统UIImpactFeedbackGenerator.FeedbackStyle原生区分手感。更早的架构性变更10.2.02021-08Android 实现从 Java 重写为 KotliniOS 引入基于 expo-modules-core Sweet API 的实验性 Swift 实现并全面从unimodules/core迁移到expo-modules-core11.1.02021-12移除遗留 Objective-C 实现pod 名改为ExpoHapticsiOS 实现简化为枚举即参数11.2.02022-04JS 与原生通信改用JSI host object取代旧桥接模块这是 expo-modules-core 现代化架构的标志性事件12.1.02022-12Android 迁移到新版 Expo modules API12.7.02023-06放弃 Android SDK 21/22即 Android 5.x 及更早12.4.02023-06修复 Gradle 8 构建警告14.0.02024-10Web 实现导出对齐原生支持expo/dom-webview下的 DOM 组件场景并修复 Web 端打包错误。三端底层实现原理iOSUIFeedbackGenerator 家族ios/HapticsModule.swift 的实现非常精简三个函数分别实例化UINotificationFeedbackGenerator、UIImpactFeedbackGenerator、UISelectionFeedbackGenerator统一遵循prepare() → 触发的两步模式并通过.runOnQueue(.main)保证在主线程执行。枚举通过Enumerable协议与 JS 侧字符串一一映射AsyncFunction(impactAsync) { (style: ImpactStyle) in let generator UIImpactFeedbackGenerator(style: style.toFeedbackStyle()) generator.prepare() generator.impactOccurred() } .runOnQueue(.main)历史上 12.0.1 曾修复Feedback Generator 不在主线程调用导致 iOS 偶发崩溃的问题Fixed rare crash on iOS when using Feedback Generators API not on the main thread这与 Swift 实现中强制主线程执行的设计一脉相承。AndroidVibrator 与 performHapticFeedback 双通道HapticsModule.kt 是理解 Android 侧的关键振动器获取API 31Android 12及以上通过VibratorManager.defaultVibrator获取更早版本使用已弃用的Context.VIBRATOR_SERVICE单例vibrate 通道notificationAsync/impactAsync/selectionAsync均走vibrate(type)——API 26 以上用VibrationEffect.createWaveform(timings, amplitudes, -1)构造带振幅的波形-1表示不重复旧系统退回oldSDKPattern。HapticsVibrationType见 arguments/HapticsVibrationType.kt正是为此封装的数据类performHapticFeedback 通道performAndroidHapticsAsync从currentActivity找到根内容视图调用View.performHapticFeedback(type.toHapticFeedbackType())必须运行在主队列Queues.MAIN。该通道无需振动权限是官方推荐的方向。WebVibration API iOS Safari 开关 Hacksrc/ExpoHaptics.web.ts 定义了与三端一致的振动模式表类型模式msSuccess[40, 100, 40]Warning[50, 100, 50]Error[60, 100, 60, 100, 60]Light[40]Medium[50]Heavy[60]Soft[35]Rigid[45]selection[50]实现策略分三层优先使用navigator.vibrate(pattern)若不可用典型即 iOS Safari则判断是否为触屏设备pointer: coarse若是则通过隐藏 checkbox 的click()触发系统开关反馈iOSSwitchHapticnotificationAsync还会根据类型决定脉冲次数Error 3 次、其余 2 次间隔 120ms。破坏性变更速查升级到新版前的检查清单综合 CHANGELOG以下破坏性变更最可能影响现有代码版本 10.0.0 起废弃的notification、impact、selection三个旧方法被移除必须改用带Async后缀的新 APIiOS 部署目标持续提升若工程最低系统版本低于 16.456.0.0 起、15.114.0.0 起、13.412.8.0 起需要评估升级Android 最低 SDK 抬升12.7.0 放弃 API 21/22compileSdk/targetSdk 分别升至 3312.2.0、3412.8.0Android 振动 API 换代14.1.0 起官方推荐performAndroidHapticsAsync取代Vibrator通道新的AndroidHaptics枚举需要按系统版本适配构建基础设施模块改用 expo modules gradle plugin14.1.0迁移到 expo-modules-core / JSI10.2.0 / 11.2.0——这些都要求宿主工程使用兼容版本的 Expo SDK 与 React Native。总结从 CHANGELOG 与源码的对照可以看出expo-haptics 的演进始终围绕三条主线iOS 保持对系统 UIFeedbackGenerator 的紧密映射并持续抬高最低版本Android 从粗放的Vibrator振动走向系统化的performHapticFeedback场景反馈Web 从零支持逐步补齐 Vibration API 与 iOS Safari 降级方案。对于应用开发者本文的关键建议是优先使用performAndroidHapticsAsync获得与 iOS 一致的手感与更小的权限面在升级模块前对照破坏性变更清单核对工程的最低系统版本与废弃 API 使用情况Web 场景下注意 iOS Safari 的反馈效果与桌面浏览器无反馈的差异。【免费下载链接】expoAn open-source framework for making universal native apps with React. Expo runs on Android, iOS, and the web.项目地址: https://gitcode.com/GitHub_Trending/ex/expo创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价