Flutter 鸿蒙 haptic_kit 2.2.0 使用实战:按钮触感、波形与取消控制
三方库仓库: https://atomgit.com/oh-flutter/haptic_kit
OHOS 适配分支:
feat/ohos_haptic_kit_2.2.0本文锁定版本:
b6554f75bbd94b30ab5d34cc55d270570dfe8bd5完整 Demo: haptic_kit/example(受测提交)
一、当前真机结果

图 1:签名 HAP 已在 CHZ-AL00 / HarmonyOS 7.0.0.105 上启动,页面包含语义触感、波形、预设和取消入口。截图只能证明页面启动,不能证明手感。




| 检查项 | 当前结论 |
|---|---|
| 固定提交依赖 | 通过,必须使用适配分支提交,默认 main 无 OHOS 代码 |
| 静态检查与构建 | 最终提交通过 |
| 自动化 | 63 项 Dart 契约测试及最终 7 项 ArkTS 取消竞态回归通过 |
| 真机启动 | 通过 |
| 物理振感 | 待人工确认,属于发布阻塞项 |
二、选用哪一层 API
haptic_kit 同时提供低层振动和带触感的 Widget。我的使用原则是:离散 UI 操作用 Haptics,持续或可取消振动用 Vibration,复杂节奏用 HapticPattern,已有交互组件则优先使用库里的 HapticToggle、HapticSlider 等封装。
| API | 适合场景 | 关键边界 |
|---|---|---|
Haptics.impact() | 按钮按下、卡片吸附 | 短促语义反馈 |
Haptics.notification() | 成功、警告、错误 | 不替代视觉提示 |
Haptics.selection() | 滑块刻度、选择器 | 高频调用要节制 |
Vibration.vibrate() | 明确时长的一次振动 | duration 必须大于 0 |
Vibration.vibrateWaveform() | 自定义时序或重复提醒 | 重复播放必须提供取消入口 |
HapticCapabilities.query() | 运行时能力判断 | 查询成功不等于主观触感验收 |
三、环境、依赖和权限
本文使用 Flutter OH 3.41.10-ohos-1.0.1、Dart 3.11.5、DevEco Studio 26.0.0 Release、HarmonyOS API 26 和 CHZ-AL00。3.44.9+ohos-0.0.1-canary1 是预览标签,不是本次实测环境。
仓库默认 main 仍停在上游 602b6c5...,没有 OHOS 目录。只写 Git URL 会取错代码,必须固定适配提交:
dependencies:
haptic_kit:
git:
url: https://atomgit.com/oh-flutter/haptic_kit.git
ref: b6554f75bbd94b30ab5d34cc55d270570dfe8bd5
flutter pub get
插件 HAR 声明 ohos.permission.VIBRATE。构建最终 HAP 后应核对权限合并;该权限无需业务页面主动弹窗申请。

图 2:默认分支与 OHOS 适配分支不同,依赖不能省略 ref。
四、先查能力,再选择反馈
import 'package:haptic_kit/haptic_kit.dart';
Future<void> playConfirmation() async {
final HapticCapabilities capabilities =
await HapticCapabilities.query();
if (!capabilities.hasVibrator) return;
if (capabilities.supportsImpactFeedback) {
await Haptics.notification(HapticNotificationStyle.success);
} else {
await Vibration.vibrate(duration: const Duration(milliseconds: 80));
}
}
能力查询用于选择路径,不能当作“用户一定能感知到”的证明。应用还应尊重自己的触感开关:
HapticSettings.enabled = userPreferences.hapticsEnabled;
关闭后所有播放调用成为无操作,但能力查询和 Vibration.cancel() 仍可执行。这样可以确保用户关闭触感时,不必在每个按钮前重复写判断。
五、单次、波形和取消
Future<void> playWarningPattern() async {
try {
await Vibration.vibrateWaveform(
timings: const <Duration>[
Duration.zero,
Duration(milliseconds: 100),
Duration(milliseconds: 80),
Duration(milliseconds: 180),
],
amplitudes: const <int>[0, 100, 0, 220],
repeat: -1,
);
} on VibrationException catch (error) {
debugPrint('haptic failed: $error');
}
}
Future<void> stopWarningPattern() => Vibration.cancel();
参数校验在 Dart 层完成:时长必须为正,幅度为 1 到 255,波形的 timings/amplitudes 数量要匹配。重复播放时,页面必须提供停止按钮,并在离开业务流程前 await Vibration.cancel()。
取消还有一个不容易看出的竞态:能力查询可能还没返回,用户已经点击停止。最终提交用 generation 隔离旧任务,保证晚到查询不会在取消后重新启动振动。

图 3:能力查询、预置效果、普通振动降级和取消代次保护。
六、一个可复用的按钮流程
class ConfirmButton extends StatefulWidget {
const ConfirmButton({super.key, required this.onConfirmed});
final Future<void> Function() onConfirmed;
State<ConfirmButton> createState() => _ConfirmButtonState();
}
class _ConfirmButtonState extends State<ConfirmButton> {
bool _busy = false;
String? _error;
Future<void> _confirm() async {
if (_busy) return;
setState(() {
_busy = true;
_error = null;
});
try {
await widget.onConfirmed();
await Haptics.notification(HapticNotificationStyle.success);
} on VibrationException catch (error) {
if (mounted) setState(() => _error = error.message);
} finally {
if (mounted) setState(() => _busy = false);
}
}
Widget build(BuildContext context) => Column(
children: <Widget>[
FilledButton(onPressed: _busy ? null : _confirm, child: const Text('确认')),
if (_error != null) Text(_error!),
],
);
}
业务操作成功后再发 success 触感,不能按钮一按就先震“成功”。触感始终是补充反馈,错误、成功和可访问性状态仍需要视觉或语音表达。
七、检查和人工验收

图 4:Dart 契约和最终 ArkTS 取消竞态回归的实际统计。

图 5:最终提交的 HAP 与依赖锁定证据。

图 6:当前已完成与待完成项;物理振感不能由截图替代。
人工验收至少要确认 light/medium/heavy 能否区分,success/warning/error 时序是否合理,单次时长、波形节奏、重复取消后是否立即停止,以及不支持高清触感时的普通振动降级。每一项都要由操作者实际感知并记录。
八、常见问题
Q1:依赖成功但 OHOS 上 MissingPlugin
- 现象:
pub get正常,运行时插件未注册。 - 原因: 依赖落到默认
main,该分支没有 OHOS 代码。 - 解决方法: 固定
b6554f7...并核对resolved-ref。 - 验证结果: 适配提交 HAP 可构建并在真机启动。
Q2:取消后又出现一次振动
- 现象: 点击 cancel 时能力查询仍在进行,稍后又开始播放。
- 原因: 旧异步结果越过取消边界。
- 解决方法: 使用包含 generation 修复的最终提交,不要锁定早期适配 SHA。
- 验证结果: 7 项 ArkTS 回归覆盖取消和晚到能力结果。
Q3:prepare 返回 false 是失败吗
- 现象: 调用
Haptics.prepare()得到 false。 - 原因: 某些平台没有可预热的生成器,false 表示无操作,不表示后续触感一定失败。
- 解决方法: 把 prepare 当可选优化,实际播放按能力与异常决定。
- 验证结果: 当前物理结果仍待人工确认,不能只用返回值下结论。
九、总结
使用 haptic_kit 时最重要的是选对 API 层、尊重用户开关、为重复波形提供取消,并固定包含取消竞态修复的适配提交。代码和 HAP 已具备复现条件,但本篇仍处于待发布状态,最后一步是完成真机物理振感验收。
十、参考链接
欢迎加入CPF-Flutter 鸿蒙社区:https://atomgit.com/CPF-Flutter
更多推荐



所有评论(0)