react-native-avoid-softinput:基于 React Native 鸿蒙生态的键盘避让组件项目

输入框防键盘遮挡适配库

Branch3Tags2
FilesLast commitLast update
17 days ago
17 days ago
18 days ago
1 month ago
1 month ago
1 month ago
1 month ago
27 days ago
18 days ago
17 days ago
17 days ago
1 month ago
17 days ago
1 month ago

@hxa-rn/react-native-avoid-softinput

react-native-avoid-softinput 基于上游 react-native-avoid-softinput 开发。如果在使用过程中有任何问题,欢迎在GitCode提交Issue,会及时跟进。

项目介绍

react-native-avoid-softinput 为 React Native 应用提供软键盘避让能力:监听软键盘显示、隐藏、高度变化和已施加偏移变化,在输入框可能被遮挡时调整 RN 视图位置或滚动容器余量,并在键盘收起后复位。

@hxa-rn/react-native-avoid-softinput 是 OpenHarmony(RNOH / Fabric 架构)适配版。npm 包名为 @hxa-rn/react-native-avoid-softinput,鸿蒙侧 HAR 的 ohpm 包名为 @oh-rn/react-native-avoid-softinput;两者不要混用。包内同时声明 harmony.alias: "react-native-avoid-softinput",便于 RNOH 按上游业务名解析。适配面包括:

  • 1 个 TurboModule:AvoidSoftInput
  • 15 个 TurboModule 方法
  • 1 个 Fabric 组件:AvoidSoftInputView
  • 7 个组件 props
  • 4 个组件事件
  • 4 个 device 事件
  • 5 个 hooks

集成指南

本节用于接入已有 RN 鸿蒙应用;运行本仓库示例请参见「快速验证(运行 Example)」。

1. 安装适配包

安装 npmjs 上的正式版本:

npm install @hxa-rn/react-native-avoid-softinput@5.0.1 --save-exact --legacy-peer-deps

安装包已包含 JS/类型产物、鸿蒙源码和 harmony/avoid_softinput.har。peerDependencies 为 {"react-native":">=0.72"};还需已有可运行的 RNOH 宿主工程。

2. 配置 Metro 并导入

适配包已声明 harmony.alias。宿主 metro.config.js 合并以下配置,并保留原有的自定义设置:

const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');
const {createHarmonyMetroConfig} = require('@react-native-oh/react-native-harmony/metro.config');

module.exports = mergeConfig(
  getDefaultConfig(__dirname),
  createHarmonyMetroConfig({
    reactNativeHarmonyPackageName: '@react-native-oh/react-native-harmony',
  }),
);

业务代码:

import {AvoidSoftInput, AvoidSoftInputView} from '@hxa-rn/react-native-avoid-softinput';

3. 注册鸿蒙原生模块

本包声明了 Autolinking 元数据:CMake 目标 avoid_softinput,ohpm 包 @oh-rn/react-native-avoid-softinput,C++ / ETS 类 AvoidSoftinputPackage。宿主启用 RNOH Autolinking 后,应检查生成的 HAR 依赖、CMake 链接及 C++ / ETS Package 注册是否齐全;已自动注册时不要重复手动注册。

Autolinking 不可用时,保留宿主已有配置,补齐以下四处:

  1. 在 harmony/entry/oh-package.json5 的 dependencies 追加下项,然后在 harmony/entry 执行 ohpm install 并同步工程:
"@oh-rn/react-native-avoid-softinput": "file:../../node_modules/@hxa-rn/react-native-avoid-softinput/harmony/avoid_softinput.har"
  1. 在 harmony/entry/src/main/cpp/CMakeLists.txt 添加子目录,并在已有 add_library(rnoh_app ...) 之后链接:
set(OH_MODULE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../oh_modules")
add_subdirectory("${OH_MODULE_DIR}/@oh-rn/react-native-avoid-softinput/src/main/cpp" ./avoid_softinput)
# 放在 rnoh_app 目标创建之后:
target_link_libraries(rnoh_app PUBLIC avoid_softinput)
  1. 在 harmony/entry/src/main/cpp/PackageProvider.cpp 添加头文件,并把实例加入已有 getPackages 返回集合(本仓库模板可加入 ManualLinkingPackage 列表):
#include "AvoidSoftinputPackage.h"

// 加入已有 Package 集合:
std::make_shared<rnoh::AvoidSoftinputPackage>(ctx)
  1. 在 harmony/entry/src/main/ets/RNPackagesFactory.ets 添加默认导入,并把实例加入已有 createRNPackages 返回数组:
import AvoidSoftinputPackage from '@oh-rn/react-native-avoid-softinput';

// 加入 createRNPackages(ctx) 返回数组:
new AvoidSoftinputPackage(ctx)

确保宿主 RNApp 使用上述 createRNPackages,并启用 enableCAPIArchitecture: true。完成后重新生成宿主 Bundle、构建并安装 HAP;只刷新 JS 不会加载新增的原生模块。若 HAR 内 RNOH 相对依赖无法解析,在宿主鸿蒙根 oh-package.json5 的 overrides 中将 @rnoh/react-native-openharmony 指向宿主正在使用的同一 RNOH HAR,勿混用 debug/release 或不同版本。

ArkTS 组件名(Autolinking 与手动接入都需要):AvoidSoftInputView 由本库的 ArkTS 组件渲染,Autolinking 不会修改宿主页面。请在宿主创建 RNApp 的页面(RNOH 工程模板为 harmony/entry/src/main/ets/pages/Index.ets)的 rnInstanceConfig 中加入组件名,否则该组件不渲染(与本仓示例相同):

RNApp({
  rnInstanceConfig: {
    createRNPackages,
    enableCAPIArchitecture: true,
    arkTsComponentNames: ['AvoidSoftInputView'],
    // ...保留宿主原有配置
  },
  // ...保留宿主原有参数
})

本库本体不要求额外系统权限。

使用说明

基础避让

import React from 'react';
import { TextInput } from 'react-native';
import { AvoidSoftInputView } from '@hxa-rn/react-native-avoid-softinput';

export default function FormView() {
  return (
    <AvoidSoftInputView
      style={{ flex: 1 }}
      enabled={true}
      avoidOffset={40}
      easing="easeInOut"
      showAnimationDuration={660}
      hideAnimationDuration={220}
    >
      <TextInput />
    </AvoidSoftInputView>
  );
}

事件订阅

import { AvoidSoftInput } from '@hxa-rn/react-native-avoid-softinput';

const subscription = AvoidSoftInput.onSoftInputShown(({ softInputHeight }) => {
  console.log(softInputHeight);
});

subscription.remove();

接口文档

AvoidSoftInputView props:

Prop 类型 默认值 说明
enabled boolean true 是否启用避让
avoidOffset number 0 额外避让偏移
easing 'easeIn' | 'easeInOut' | 'easeOut' | 'linear' 'linear' 位移动画缓动
showAnimationDelay number 0 键盘显示位移动画延迟,单位 ms
showAnimationDuration number 660 键盘显示位移动画时长,单位 ms
hideAnimationDelay number 0 键盘隐藏复位动画延迟,单位 ms
hideAnimationDuration number 220 键盘隐藏复位动画时长,单位 ms

AvoidSoftInputView 组件事件:

事件 Payload
onSoftInputShown { softInputHeight: number }
onSoftInputHidden { softInputHeight: number }
onSoftInputHeightChange { softInputHeight: number }
onSoftInputAppliedOffsetChange { appliedOffset: number }

AvoidSoftInput 方法:

方法 说明
setEnabled(enabled) 设置模块路径避让启用状态
setAvoidOffset(offset) 设置模块路径额外偏移
setEasing(easing) 设置模块路径缓动
setShowAnimationDelay(delay) 设置键盘显示动画延迟
setShowAnimationDuration(duration) 设置键盘显示动画时长
setHideAnimationDelay(delay) 设置键盘隐藏动画延迟
setHideAnimationDuration(duration) 设置键盘隐藏复位动画时长
setShouldMimicIOSBehavior(value) Android 专属门面方法,HarmonyOS 侧无害返回
setAdjustNothing() Android 专属门面方法,HarmonyOS 侧无害返回
setAdjustPan() Android 专属门面方法,HarmonyOS 侧无害返回
setAdjustResize() Android 专属门面方法,HarmonyOS 侧无害返回
setAdjustUnspecified() Android 专属门面方法,HarmonyOS 侧无害返回
setDefaultAppSoftInputMode() Android 专属门面方法,HarmonyOS 侧无害返回
addListener(eventName) RN 事件订阅计数接口
removeListeners(count) RN 事件订阅计数接口

Hooks:

useSoftInputShown、useSoftInputHidden、useSoftInputHeightChanged、useSoftInputAppliedOffsetChanged、useSoftInputState。

Device 事件:

softInputShown、softInputHidden、softInputHeightChanged、softInputAppliedOffsetChanged。

快速验证(运行 Example)

前置条件

依赖 版本要求
Node.js >= 20(示例工程 engines 要求)
DevEco Studio 6.1.1 及以上(示例 targetSdkVersion 为 6.1.1(24))
HarmonyOS SDK API 18+(example/harmony 的 compatibleSdkVersion 为 5.1.0(18))
路径 Windows 下仓库根目录的完整路径不超过 40 个字符,否则原生构建的中间文件路径会超过系统上限

运行步骤

1. 克隆仓库

git clone -b br_rnoh0.72 https://gitcode.com/hxa-rn/react-native-avoid-softinput.git
cd react-native-avoid-softinput

Windows 下可在克隆时指定短目录名,例如 git clone -b br_rnoh0.72 https://gitcode.com/hxa-rn/react-native-avoid-softinput.git C:\rasi。

2. 进入 example 目录,安装依赖

cd example
npm install --legacy-peer-deps

Example 从 npm 公仓安装 @hxa-rn/react-native-avoid-softinput@5.0.1,不需要在仓根执行 npm pack。

3. 生成 JS Bundle

npm run dev

产物:harmony/entry/src/main/resources/rawfile/bundle.harmony.js

4. 用 DevEco Studio 打开鸿蒙工程

  • 打开 DevEco Studio,选择 example/harmony 目录
  • 首次构建请在 File → Project Structure → Signing Configs 勾选 Automatically generate signature,Apply 后 Sync
  • 等待 Sync 完成

5. 编译并运行 HAP

在 DevEco Studio 中点击运行按钮,将 HAP 安装到设备。

example_auto(自动化用例工程)步骤相同,把 example 换成 example_auto 即可,两者的依赖与构建输出相互独立。

注意:Example 已预置 Package 注册、Metro alias 与 HAR 依赖,无需手动 Link。编 HAP 前必须先执行 npm run dev;改过 JS 后重新执行再运行。

常见问题

  • 找不到 JS 模块:检查适配包安装、Metro 别名及对应入口,修改 Metro 后重启打包进程。
  • 找不到 npm 包或 HAR:核对 example/node_modules/@hxa-rn/react-native-avoid-softinput/harmony/avoid_softinput.har 是否存在;不要将 example_auto 的 node_modules 当成 example 的依赖。
  • 原生模块或组件未注册:检查 HAR、CMake、C++ 和 ETS 注册,排除重复注册并重建 HAP。
  • SDK / 签名报错:按当前工程配置安装对应 SDK,并重新配置本机签名。
  • Ninja .rsp 创建失败:查看完整日志;确认是路径长度问题后,缩短工程目录、清理旧路径构建缓存再构建。

约束与限制

兼容性:

项 值
上游基线 react-native-avoid-softinput@5.0.0
适配版本 5.0.0(与上游基线同号)
RN / RNOH RN 0.72.5 + @react-native-oh/react-native-harmony@0.72.143
鸿蒙最低兼容 API API 18(compatibleSdkVersion 5.1.0(18))
目标 API API 24(targetSdkVersion 6.1.1(24))
运行系统 HarmonyOS
本 npm 版本验证范围 Node 22 + DevEco Studio 6.1.1 / SDK API 24;example 与 example_auto 编译出 HAP。未以本次 npm 包执行真机功能验证

权限:

本库 HAR module.json5 的 requestPermissions 为空数组。本库本体及其三方依赖不声明任何系统权限。

使用约束:

  • AvoidSoftInputView 是 Fabric 组件,不是 PlatformView,也不使用 TextureView。
  • AvoidSoftInputView 需要加入 arkTsComponentNames: ['AvoidSoftInputView'](见「集成指南」第 3 步),否则组件无法由 RNOH ArkTS builder 渲染。
  • Android 专属 windowSoftInputMode 相关方法在 HarmonyOS 侧作为兼容门面保留,调用后无害返回,不声明等价系统窗口模式能力。
  • softInputAppliedOffsetChanged 在动画期可能逐帧触发,若在该回调里打印日志或触发重渲染,容易刷屏或造成卡顿,业务侧按需节流。

开源 License

本项目基于 MIT License 开源,与上游协议一致。

问题反馈渠道

使用过程中发现任何问题,欢迎在GitCode 提交 Issue,也欢迎提交 PR 参与共建。

Introduction

输入框防键盘遮挡适配库

Customize your domain