欢迎加入开源鸿蒙跨平台社区https://openharmonycrossplatform.csdn.net

📋 前言

在移动应用开发中,触觉反馈(Haptic Feedback)已经成为提升用户体验的重要手段之一。当用户点击按钮、滑动列表或完成某个操作时,设备产生的震动反馈能够提供直观的物理响应,增强交互的真实感和满足感。react-native-haptic-feedback 是 React Native 生态中最流行的触觉反馈库,提供了丰富的震动效果类型和跨平台支持。

🎯 库简介

基本信息

  • 库名称: react-native-haptic-feedback
  • 版本信息:
    • <=2.2.1 + @react-native-oh-tpl/react-native-haptic-feedback: 支持 RN 0.72 版本 (已废弃)
    • 2.2.2 + @react-native-ohos/react-native-haptic-feedback: 支持 RN 0.72 版本
    • 2.3.4 + @react-native-ohos/react-native-haptic-feedback: 支持 RN 0.77 版本
  • 官方仓库: https://github.com/mkuczera/react-native-haptic-feedback
  • 鸿蒙仓库: https://github.com/react-native-oh-library/react-native-haptic-feedback
  • 主要功能:
    • 📳 多种预设震动效果
    • 🎚️ 自定义震动强度
    • 🎼 自定义震动模式
    • 📱 iOS Core Haptics 支持
    • 🤖 Android Vibrator API 支持
    • 🎣 React Hook 支持

为什么需要触觉反馈?

场景 无触觉反馈 有触觉反馈
按钮点击 ⚠️ 缺乏确认感 ✅ 明确的操作反馈
滑动选择 ⚠️ 边界感知弱 ✅ 清晰的分段反馈
错误提示 ⚠️ 仅视觉提示 ✅ 视觉+触觉双重提示
成功操作 ⚠️ 反馈不明显 ✅ 满足感更强
游戏交互 ⚠️ 沉浸感不足 ✅ 增强沉浸体验

支持的震动类型

类型 说明 iOS Android HarmonyOS
impactLight 轻量冲击
impactMedium 中等冲击
impactHeavy 重度冲击
rigid 刚性冲击
soft 柔和冲击
notificationSuccess 通知成功
notificationWarning 通知警告
notificationError 通知错误
selection 选择反馈
clockTick 时钟滴答
contextClick 上下文点击
keyboardPress 键盘按下
keyboardRelease 键盘释放
keyboardTap 键盘点击
longPress 长按反馈
textHandleMove 文本手柄移动
virtualKey 虚拟按键
virtualKeyRelease 虚拟按键释放
effectClick 效果点击
effectDoubleClick 效果双击
effectHeavyClick 效果重击
effectTick 效果滴答

兼容性验证

在以下环境验证通过:

  • RNOH: 0.72.96; SDK: HarmonyOS 6.0.0 Release SDK; IDE: DevEco Studio 6.0.0.858; ROM: 6.0.0.112
  • RNOH: 0.72.33; SDK: HarmonyOS NEXT B1; IDE: DevEco Studio 5.0.3.900; ROM: Next.0.0.71
  • RNOH: 0.77.18; SDK: HarmonyOS 6.0.0 Release SDK; IDE: DevEco Studio 6.0.0.858; ROM: 6.0.0.112

📦 安装步骤

1. 安装依赖

在项目根目录执行以下命令,本文基于 RN 0.72.90 版本开发:

# RN 0.72 版本
npm install @react-native-ohos/react-native-haptic-feedback@2.2.2-rc.1

# 或者使用 yarn
yarn add @react-native-ohos/react-native-haptic-feedback@2.2.2-rc.1

2. 验证安装

安装完成后,检查 package.json 文件,应该能看到新增的依赖:

{
  "dependencies": {
    "@react-native-ohos/react-native-haptic-feedback": "2.2.2-rc.1"
  }
}

🔧 HarmonyOS 平台配置 ⭐

由于 HarmonyOS 暂不支持 AutoLink,需要手动配置原生端代码。本文提供 HAR 包引入源码引入 两种方式,可根据实际需求选择。

1. 在工程根目录的 oh-package.json5 添加 overrides 字段

打开 harmony/oh-package.json5,添加以下配置:

{
  // ... 其他配置
  "overrides": {
    "@rnoh/react-native-openharmony": "0.72.90"
  }
}

2. 权限声明

打开 harmony/entry/src/main/module.json5,声明振动权限:

{
  "module": {
    "requestPermissions": [
      // ... 其他权限
      {
        "name": "ohos.permission.VIBRATE"
      }
    ]
  }
}

💡 注意ohos.permission.VIBRATEnormal 级别权限,无需特殊签名配置。


方式一:HAR 包引入(推荐)📦

HAR 包引入方式简单快捷,适合大多数场景。

💡 提示:HAR 包位于三方库安装路径的 harmony 文件夹下。

3.1 在 entry/oh-package.json5 添加依赖

打开 harmony/entry/oh-package.json5,添加以下依赖:

"dependencies": {
  "@rnoh/react-native-openharmony": "0.72.90",
  "@react-native-ohos/react-native-haptic-feedback": "file:../../node_modules/@react-native-ohos/react-native-haptic-feedback/harmony/haptic_feedback.har"
}

3.2 同步依赖

点击 DevEco Studio 右上角的 sync 按钮,或者在终端执行:

cd harmony/entry
ohpm install

3.3 配置 CMakeLists.txt

打开 harmony/entry/src/main/cpp/CMakeLists.txt,添加以下配置:

project(rnapp)
cmake_minimum_required(VERSION 3.4.1)
set(CMAKE_SKIP_BUILD_RPATH TRUE)
set(RNOH_APP_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
set(NODE_MODULES "${CMAKE_CURRENT_SOURCE_DIR}/../../../../../node_modules")
set(OH_MODULES "${CMAKE_CURRENT_SOURCE_DIR}/../../../oh_modules")
set(RNOH_CPP_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../react-native-harmony/harmony/cpp")
set(LOG_VERBOSITY_LEVEL 1)
set(CMAKE_ASM_FLAGS "-Wno-error- unused-command-line-argument -Qunused-arguments")
set(CMAKE_CXX_FLAGS "-fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -s -fPIE -pie")
set(WITH_HITRACE_SYSTRACE 1)
add_compile_definitions(WITH_HITRACE_SYSTRACE)

add_subdirectory("${RNOH_CPP_DIR}" ./rn)

# 添加 HapticFeedback 模块(HAR方式)
add_subdirectory("${OH_MODULES}/@react-native-ohos/react-native-haptic-feedback/src/main/cpp" ./haptic-feedback)

file(GLOB GENERATED_CPP_FILES "./generated/*.cpp")

add_library(rnoh_app SHARED
    ${GENERATED_CPP_FILES}
    "./PackageProvider.cpp"
    "${RNOH_CPP_DIR}/RNOHAppNapiBridge.cpp"
)
target_link_libraries(rnoh_app PUBLIC rnoh)

# 链接 HapticFeedback 库
target_link_libraries(rnoh_app PUBLIC rnoh_haptic_feedback)

3.4 修改 PackageProvider.cpp

打开 harmony/entry/src/main/cpp/PackageProvider.cpp,添加:

#include "RNOH/PackageProvider.h"
#include "generated/RNOHGeneratedPackage.h"
#include "RNHapticFeedbackPackage.h"

using namespace rnoh;

std::vector<std::shared_ptr<Package>> PackageProvider::getPackages(Package::Context ctx) {
    return {
        std::make_shared<RNOHGeneratedPackage>(ctx),
        std::make_shared<RNHapticFeedbackPackage>(ctx),
    };
}

3.5 在 ArkTs 侧引入 Package

打开 harmony/entry/src/main/ets/RNPackagesFactory.ts,添加:

import type { RNPackageContext, RNPackage } from 'rnoh/ts';
import { RNHapticFeedbackPackage } from '@react-native-ohos/react-native-haptic-feedback/ts';

export function createRNPackages(ctx: RNPackageContext): RNPackage[] {
  return [
    // ... 其他包
    new RNHapticFeedbackPackage(ctx),
  ];
}

方式二:源码引入 📁

源码引入方式适合需要调试或修改原生代码的场景。

3.1 复制源码到 harmony 工程根目录

<RN工程>/node_modules/@react-native-ohos/react-native-haptic-feedback/harmony 目录下的源码 haptic_feedback 复制到 harmony(鸿蒙壳工程)工程根目录下。

# 复制源码目录
cp -r node_modules/@react-native-ohos/react-native-haptic-feedback/harmony/haptic_feedback harmony/

3.2 在 build-profile.json5 添加模块

打开 harmony/build-profile.json5,添加以下模块:

modules: [
  // ... 其他模块
  {
    name: 'haptic_feedback',
    srcPath: './haptic_feedback',
  }
]

💡 提示:如果存在 build-profile.template.json5 文件,也需要同步添加上述模块配置。

3.3 修改 haptic_feedback/oh-package.json5

打开 harmony/haptic_feedback/oh-package.json5,修改 react-native-openharmony 版本与项目版本一致:

{
  "dependencies": {
    "@rnoh/react-native-openharmony": "0.72.90"
  }
}

3.4 在 entry/oh-package.json5 添加依赖

打开 harmony/entry/oh-package.json5,添加以下依赖:

"dependencies": {
  "@rnoh/react-native-openharmony": "0.72.90",
  "@react-native-ohos/react-native-haptic-feedback": "file:../haptic_feedback"
}

3.5 同步依赖

点击 DevEco Studio 右上角的 sync 按钮,或者在终端执行:

cd harmony/entry
ohpm install

3.6 配置 CMakeLists.txt

打开 harmony/entry/src/main/cpp/CMakeLists.txt,添加以下配置:

project(rnapp)
cmake_minimum_required(VERSION 3.4.1)
set(CMAKE_SKIP_BUILD_RPATH TRUE)
set(RNOH_APP_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
set(NODE_MODULES "${CMAKE_CURRENT_SOURCE_DIR}/../../../../../node_modules")
set(OH_MODULES "${CMAKE_CURRENT_SOURCE_DIR}/../../../oh_modules")
set(RNOH_CPP_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../react-native-harmony/harmony/cpp")
set(LOG_VERBOSITY_LEVEL 1)
set(CMAKE_ASM_FLAGS "-Wno-error- unused-command-line-argument -Qunused-arguments")
set(CMAKE_CXX_FLAGS "-fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -s -fPIE -pie")
set(WITH_HITRACE_SYSTRACE 1)
add_compile_definitions(WITH_HITRACE_SYSTRACE)

add_subdirectory("${RNOH_CPP_DIR}" ./rn)

# 添加 HapticFeedback 模块(源码方式)
add_subdirectory("${OH_MODULES}/@react-native-ohos/react-native-haptic-feedback/src/main/cpp" ./haptic-feedback)

file(GLOB GENERATED_CPP_FILES "./generated/*.cpp")

add_library(rnoh_app SHARED
    ${GENERATED_CPP_FILES}
    "./PackageProvider.cpp"
    "${RNOH_CPP_DIR}/RNOHAppNapiBridge.cpp"
)
target_link_libraries(rnoh_app PUBLIC rnoh)

# 链接 HapticFeedback 库
target_link_libraries(rnoh_app PUBLIC rnoh_haptic_feedback)

3.7 修改 PackageProvider.cpp

打开 harmony/entry/src/main/cpp/PackageProvider.cpp,添加:

#include "RNOH/PackageProvider.h"
#include "generated/RNOHGeneratedPackage.h"
#include "RNHapticFeedbackPackage.h"

using namespace rnoh;

std::vector<std::shared_ptr<Package>> PackageProvider::getPackages(Package::Context ctx) {
    return {
        std::make_shared<RNOHGeneratedPackage>(ctx),
        std::make_shared<RNHapticFeedbackPackage>(ctx),
    };
}

3.8 在 ArkTs 侧引入 Package

打开 harmony/entry/src/main/ets/RNPackagesFactory.ts,添加:

import type { RNPackageContext, RNPackage } from 'rnoh/ts';
import { RNHapticFeedbackPackage } from '@react-native-ohos/react-native-haptic-feedback/ts';

export function createRNPackages(ctx: RNPackageContext): RNPackage[] {
  return [
    // ... 其他包
    new RNHapticFeedbackPackage(ctx),
  ];
}

同步并运行 🚀

4. 同步依赖

点击 DevEco Studio 右上角的 sync 按钮,或者在终端执行:

cd harmony/entry
ohpm install

然后编译、运行即可。

📖 API 详解

trigger(method, options)

触发触觉反馈。

参数说明

参数 类型 必填 说明
method string 震动类型
options object 配置选项

options 配置

属性 类型 默认值 说明
enableVibrateFallback boolean false 在不支持触觉反馈时是否使用普通震动
ignoreAndroidSystemSettings boolean false 是否忽略 Android 系统震动设置

使用示例

import ReactNativeHapticFeedback from 'react-native-haptic-feedback';

// 基础用法
ReactNativeHapticFeedback.trigger('impactLight');

// 带配置项
ReactNativeHapticFeedback.trigger('impactMedium', {
  enableVibrateFallback: true,
  ignoreAndroidSystemSettings: false,
});

震动类型分类

冲击反馈(Impact)

适用于按钮点击、UI 元素交互等场景。

类型 说明 使用场景
impactLight 轻量冲击 轻量级交互
impactMedium 中等冲击 常规按钮点击
impactHeavy 重度冲击 重要操作确认
rigid 刚性冲击 尖锐、快速的反馈
soft 柔和冲击 温柔、舒缓的反馈
通知反馈(Notification)

适用于操作结果提示。

类型 说明 使用场景
notificationSuccess 成功通知 操作成功提示
notificationWarning 警告通知 警告提示
notificationError 错误通知 错误提示
选择反馈(Selection)

适用于选择器、滚动列表等场景。

类型 说明 使用场景
selection 选择反馈 选择器滚动
clockTick 时钟滴答 时钟计时
contextClick 上下文点击 上下文菜单
键盘反馈(Keyboard)

适用于键盘输入场景。

类型 说明 使用场景
keyboardPress 键盘按下 按键按下
keyboardRelease 键盘释放 按键释放
keyboardTap 键盘点击 按键点击
交互反馈(Interaction)

适用于长按、拖动等场景。

类型 说明 使用场景
longPress 长按反馈 长按触发
textHandleMove 文本手柄移动 文本选择
virtualKey 虚拟按键 虚拟按键按下
virtualKeyRelease 虚拟按键释放 虚拟按键释放
效果反馈(Effect)

适用于通用交互效果。

类型 说明 使用场景
effectClick 效果点击 标准点击
effectDoubleClick 效果双击 双击操作
effectHeavyClick 效果重击 重击操作
effectTick 效果滴答 滴答效果

📱 完整示例(请确认在手机设置中打开了系统触觉反馈功能)

在这里插入图片描述

以下是一个完整的触觉反馈演示应用:

import React, { useState, useEffect } from 'react';
import {
  View,
  Text,
  TouchableOpacity,
  StyleSheet,
  ScrollView,
  Switch,
  Alert,
  Platform,
} from 'react-native';
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';

type HapticFeedbackTypes =
  | 'impactLight'
  | 'impactMedium'
  | 'impactHeavy'
  | 'rigid'
  | 'soft'
  | 'notificationSuccess'
  | 'notificationWarning'
  | 'notificationError'
  | 'selection'
  | 'clockTick'
  | 'contextClick'
  | 'keyboardPress'
  | 'keyboardRelease'
  | 'keyboardTap'
  | 'longPress'
  | 'textHandleMove'
  | 'virtualKey'
  | 'virtualKeyRelease'
  | 'effectClick'
  | 'effectDoubleClick'
  | 'effectHeavyClick'
  | 'effectTick';

interface HapticButtonProps {
  title: string;
  type: HapticFeedbackTypes;
  description: string;
  enabled?: boolean;
}

const HapticButton: React.FC<HapticButtonProps> = ({ title, type, description, enabled }) => {
  const handlePress = () => {
    if (!enabled) {
      Alert.alert('提示', '请先启用触觉反馈');
      return;
    }
    ReactNativeHapticFeedback.trigger(type, {
      enableVibrateFallback: true,
      ignoreAndroidSystemSettings: false,
    });
    Alert.alert('触觉反馈', `${title}\n${description}`);
  };

  return (
    <TouchableOpacity 
      style={[styles.hapticButton, !enabled && styles.disabledButton]} 
      onPress={handlePress} 
      activeOpacity={0.7}
    >
      <Text style={[styles.buttonTitle, !enabled && styles.disabledText]}>{title}</Text>
      <Text style={styles.buttonDesc}>{description}</Text>
    </TouchableOpacity>
  );
};

const HapticFeedbackDemo: React.FC = () => {
  const [hapticsEnabled, setHapticsEnabled] = useState(true);

  const toggleHaptics = (value: boolean) => {
    setHapticsEnabled(value);
    if (value) {
      ReactNativeHapticFeedback.trigger('impactLight', {
        enableVibrateFallback: true,
      });
    }
  };

  const impactTypes: HapticButtonProps[] = [
    { title: '轻量冲击', type: 'impactLight', description: '轻柔的触觉反馈' },
    { title: '中等冲击', type: 'impactMedium', description: '适中的触觉反馈' },
    { title: '重度冲击', type: 'impactHeavy', description: '强烈的触觉反馈' },
    { title: '刚性冲击', type: 'rigid', description: '尖锐的触觉反馈' },
    { title: '柔和冲击', type: 'soft', description: '柔和的触觉反馈' },
  ];

  const notificationTypes: HapticButtonProps[] = [
    { title: '成功通知', type: 'notificationSuccess', description: '操作成功提示' },
    { title: '警告通知', type: 'notificationWarning', description: '警告提示' },
    { title: '错误通知', type: 'notificationError', description: '错误提示' },
  ];

  const interactionTypes: HapticButtonProps[] = [
    { title: '选择反馈', type: 'selection', description: '选择器滚动' },
    { title: '时钟滴答', type: 'clockTick', description: '时钟计时' },
    { title: '长按反馈', type: 'longPress', description: '长按触发' },
    { title: '键盘按下', type: 'keyboardPress', description: '键盘输入' },
  ];

  const effectTypes: HapticButtonProps[] = [
    { title: '效果点击', type: 'effectClick', description: '标准点击效果' },
    { title: '效果双击', type: 'effectDoubleClick', description: '双击效果' },
    { title: '效果重击', type: 'effectHeavyClick', description: '重击效果' },
    { title: '效果滴答', type: 'effectTick', description: '滴答效果' },
  ];

  return (
    <ScrollView style={styles.container}>
      <View style={styles.settingSection}>
        <View style={styles.settingRow}>
          <Text style={styles.settingLabel}>启用触觉反馈</Text>
          <Switch
            value={hapticsEnabled}
            onValueChange={toggleHaptics}
            trackColor={{ false: '#767577', true: '#81b0ff' }}
            thumbColor={hapticsEnabled ? '#007AFF' : '#f4f3f4'}
          />
        </View>
        <Text style={styles.hint}>
          ⚠️ 请确保系统设置中的震动功能已开启
        </Text>
      </View>

      <View style={styles.section}>
        <Text style={styles.sectionTitle}>💪 冲击反馈</Text>
        <View style={styles.buttonGrid}>
          {impactTypes.map((item) => (
            <HapticButton key={item.type} {...item} enabled={hapticsEnabled} />
          ))}
        </View>
      </View>

      <View style={styles.section}>
        <Text style={styles.sectionTitle}>📢 通知反馈</Text>
        <View style={styles.buttonGrid}>
          {notificationTypes.map((item) => (
            <HapticButton key={item.type} {...item} enabled={hapticsEnabled} />
          ))}
        </View>
      </View>

      <View style={styles.section}>
        <Text style={styles.sectionTitle}>👆 交互反馈</Text>
        <View style={styles.buttonGrid}>
          {interactionTypes.map((item) => (
            <HapticButton key={item.type} {...item} enabled={hapticsEnabled} />
          ))}
        </View>
      </View>

      <View style={styles.section}>
        <Text style={styles.sectionTitle}>✨ 效果反馈</Text>
        <View style={styles.buttonGrid}>
          {effectTypes.map((item) => (
            <HapticButton key={item.type} {...item} enabled={hapticsEnabled} />
          ))}
        </View>
      </View>

      <View style={styles.footer}>
        <Text style={styles.footerText}>
          💡 提示:请在真机上测试以体验触觉反馈效果
        </Text>
      </View>
    </ScrollView>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#f5f5f5',
  },
  settingSection: {
    backgroundColor: '#fff',
    padding: 16,
    marginBottom: 12,
  },
  settingRow: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
  },
  settingLabel: {
    fontSize: 16,
    color: '#333',
  },
  hint: {
    fontSize: 12,
    color: '#999',
    marginTop: 8,
  },
  section: {
    backgroundColor: '#fff',
    padding: 16,
    marginBottom: 12,
  },
  sectionTitle: {
    fontSize: 18,
    fontWeight: '600',
    color: '#333',
    marginBottom: 12,
  },
  buttonGrid: {
    flexDirection: 'row',
    flexWrap: 'wrap',
    marginHorizontal: -6,
  },
  hapticButton: {
    width: '48%',
    marginHorizontal: '1%',
    marginBottom: 12,
    padding: 16,
    backgroundColor: '#f0f8ff',
    borderRadius: 12,
    borderWidth: 1,
    borderColor: '#007AFF',
  },
  disabledButton: {
    backgroundColor: '#f5f5f5',
    borderColor: '#ccc',
  },
  disabledText: {
    color: '#999',
  },
  buttonTitle: {
    fontSize: 16,
    fontWeight: '600',
    color: '#007AFF',
    marginBottom: 4,
  },
  buttonDesc: {
    fontSize: 12,
    color: '#666',
  },
  footer: {
    padding: 20,
    alignItems: 'center',
  },
  footerText: {
    fontSize: 14,
    color: '#666',
    textAlign: 'center',
  },
});

export default HapticFeedbackDemo;

🔬 高级用法

1. 按钮组件集成

import { TouchableOpacity, Text, StyleSheet } from 'react-native';
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';

interface HapticButtonProps {
  title: string;
  onPress: () => void;
  hapticType?: 'impactLight' | 'impactMedium' | 'impactHeavy';
}

export const HapticButton: React.FC<HapticButtonProps> = ({
  title,
  onPress,
  hapticType = 'impactLight',
}) => {
  const handlePress = () => {
    ReactNativeHapticFeedback.trigger(hapticType, {
      enableVibrateFallback: true,
    });
    onPress();
  };

  return (
    <TouchableOpacity style={styles.button} onPress={handlePress}>
      <Text style={styles.text}>{title}</Text>
    </TouchableOpacity>
  );
};

const styles = StyleSheet.create({
  button: {
    padding: 16,
    backgroundColor: '#007AFF',
    borderRadius: 8,
    alignItems: 'center',
  },
  text: {
    color: '#fff',
    fontSize: 16,
    fontWeight: '600',
  },
});

2. 滑动选择器集成

import { ScrollView, Text, StyleSheet } from 'react-native';
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';

const HapticPicker: React.FC = () => {
  const items = ['选项1', '选项2', '选项3', '选项4', '选项5'];
  let lastItemIndex = -1;

  const handleScroll = (event: any) => {
    const contentOffset = event.nativeEvent.contentOffset.x;
    const itemWidth = 100;
    const currentIndex = Math.round(contentOffset / itemWidth);

    if (currentIndex !== lastItemIndex && currentIndex >= 0) {
      ReactNativeHapticFeedback.trigger('selection', {
        enableVibrateFallback: true,
      });
      lastItemIndex = currentIndex;
    }
  };

  return (
    <ScrollView
      horizontal
      pagingEnabled
      onScroll={handleScroll}
      scrollEventThrottle={16}
      style={styles.container}
    >
      {items.map((item, index) => (
        <Text key={index} style={styles.item}>
          {item}
        </Text>
      ))}
    </ScrollView>
  );
};

const styles = StyleSheet.create({
  container: {
    height: 60,
  },
  item: {
    width: 100,
    textAlign: 'center',
    lineHeight: 60,
    fontSize: 16,
  },
});

3. React Hook 封装

import { useCallback, useState } from 'react';
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';

type HapticType =
  | 'impactLight'
  | 'impactMedium'
  | 'impactHeavy'
  | 'notificationSuccess'
  | 'notificationWarning'
  | 'notificationError'
  | 'selection';

interface HapticOptions {
  enableVibrateFallback?: boolean;
  ignoreAndroidSystemSettings?: boolean;
}

export const useHaptic = (defaultOptions?: HapticOptions) => {
  const [enabled, setEnabled] = useState(true);

  const trigger = useCallback(
    (type: HapticType, options?: HapticOptions) => {
      if (enabled) {
        ReactNativeHapticFeedback.trigger(type, {
          enableVibrateFallback: true,
          ignoreAndroidSystemSettings: false,
          ...defaultOptions,
          ...options,
        });
      }
    },
    [enabled, defaultOptions]
  );

  return {
    trigger,
    enabled,
    setEnabled,
  };
};

// 使用示例
const MyComponent = () => {
  const { trigger, enabled, setEnabled } = useHaptic({
    enableVibrateFallback: true,
  });

  return (
    <TouchableOpacity onPress={() => trigger('impactMedium')}>
      <Text>点击我</Text>
    </TouchableOpacity>
  );
};

⚠️ 常见问题

Q1: 震动没有反馈?

解决方案

  1. 检查权限是否正确声明
  2. 确认在真机上测试(模拟器不支持)
  3. 检查设备是否开启了震动功能

Q2: 震动效果不一致?

解决方案

  • 不同设备的震动马达性能不同
  • HarmonyOS 对各类型震动有统一实现

📚 参考资料

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐