RN适配OpenHarmony:KeyboardAvoidingView失效的根因与避让方案

发布时间:2026/10/20 1:48:52
RN适配OpenHarmony:KeyboardAvoidingView失效的根因与避让方案
从应用市场的React Native基础包迁移到OpenHarmony平台后很多同事第一次遇到键盘避让问题都会懵明明在iOS和Android上跑得好好的底部输入框换到鸿蒙系统上软键盘一弹出来输入框要么被直接盖住要么页面被顶得乱七八糟像是失忆了一样。这个问题看起来不大却是很多RN应用在做OpenHarmony适配时的第一道坎。今天这篇就专门聊聊KeyboardAvoidingView在OpenHarmony平台上失效的原因以及我实际摸索出来的那几套能用、能落地的避让方案。这篇文章适合正在做React Native以下简称RN应用OpenHarmony适配的开发者也适合刚接触OpenHarmony系统、准备把自己的RN代码迁移过来的朋友。我会先讲清楚问题背后的机制差异再给出一套不需要改原生代码的应急方案然后说说真正治本的做法最后把不同页面结构下的选型建议整理成清单方便你直接抄作业。1. 为什么OpenHarmony上的RN应用键盘一弹出来就遮住输入框先说个前提这个问题不是RN本身的Bug也不是OpenHarmony系统不让你好好输入而是三套系统的软键盘协调机制从根上就不一样。RN的KeyboardAvoidingView在iOS和Android上能正常工作是因为这两个平台各自有一套成熟的窗口避让协议键盘的高度变化能被系统可靠地通知给应用。OpenHarmony虽然也有类似的机制但从RN应用的角度看桥接层对键盘事件的传递并不完整于是JS侧拿不到该拿的键盘高度或者拿到了也晚了一步避让自然就失效了。1.1 三个平台的键盘协调逻辑差别比想象中大iOS的做法是系统级别地顶视图键盘弹出时系统会重新布局整个window把第一响应者往上推。RN通过键盘事件keyboardWillShow能在动画开始前拿到精确的键盘最终高度所以KeyboardAvoidingView的padding和height两种模式都有很好的表现几乎不会闪屏。Android的默认行为则依赖窗口的softInputMode。当window被设置为adjustResize时软键盘弹出会让Activity的可绘制区域变小整个DecorView跟着重新布局RN也能在keyboardDidShow触发时感知到尺寸变化。但问题在于很多使用手势导航或全屏沉浸式样式的Android应用会把这个模式改掉甚至直接用adjustPan于是键盘避让就变得玄学了。OpenHarmony这边窗口是有键盘避让模式的文档里能看到一些相关设置项比如是否全屏布局、键盘弹出时的避让策略。但在RN on OpenHarmony这套框架里键盘事件从原生层到JS层的传递链路是相对薄弱的。我在某开发者的调试日志里看到的实际情况是键盘弹出来了系统窗口其实也做了避让但RN根视图拿到的窗口高度没有同步变化KeyboardAvoidingView的监听事件压根没触发于是页面纹丝不动底部输入框被挡住。1.2 实际翻车现场最常见的三种错乱表现完全没反应键盘弹出后页面一动不动输入框被软键盘盖住用户只能盲打。这是最典型的症状原因就是JS侧没收到键盘事件。双倍避让页面反而被顶上去太多输入框和键盘之间隔了一大片空白像是有个透明条在中间。这种通常是原生系统已经在避让RN又在JS层补了个高度两边叠加了。避让残留收起键盘后页面没有回到原始位置底部留着一块空白区域要等下一次布局触发才能恢复。这多半是事件时序没处理好高度恢复为0的操作比键盘收起动画晚了一步。1.3 一个最小的复现Demo帮你快速确认问题你可以用最简单的页面做个验证一个普通View底部放一个TextInput外面包上KeyboardAvoidingViewbehavior设为padding然后在OpenHarmony真机上跑一下。import React from react; import { KeyboardAvoidingView, TextInput, View, Text, StyleSheet } from react-native; function ReproduceScreen() { return ( KeyboardAvoidingView style{styles.flex} behaviorpadding keyboardVerticalOffset{0} View style{styles.content} Text键盘避让复现/Text /View TextInput style{styles.input} placeholder在鸿蒙上试试输入 / /KeyboardAvoidingView ); } const styles StyleSheet.create({ flex: { flex: 1 }, content: { flex: 1, justifyContent: center, alignItems: center }, input: { height: 44, margin: 16, borderWidth: 1, borderColor: #ccc, borderRadius: 8, paddingHorizontal: 12, }, }); export default ReproduceScreen;如果键盘弹出后这个输入框没有任何上移动画说明KS事件没有被RN收到基本可以断定是桥接层的事件投递问题。那接下来就要搞清楚KeyboardAvoidingView内部到底在做哪些工作以及它在OpenHarmony上究竟是哪一环掉了链子。2. KeyboardAvoidingView失效的根因JS层、桥接层、窗口层三层机制错位我在排查这个问题时花了不少时间在到底是谁的锅上。最后发现这不是单一环节的问题而是RN、RN的OpenHarmony桥接层、OpenHarmony窗口三层相互之间没有对齐缺了任何一环避让都做不起来。2.1 KeyboardAvoidingView看起来简单内部其实做了不少事KeyboardAvoidingView的核心逻辑并不复杂它通过监听键盘事件的endCoordinates算出键盘高度然后选择一种方式让内容避开键盘behaviorheight直接修改容器的高度让子布局可用的垂直空间缩小相当于把整个页面压短。这对单输入框、内容不滚动的页面比较合适。behaviorpadding给容器底部加padding视觉上是把内容往上推配合ScrollView类组件使用效果最稳定。behaviorposition修改容器本身的position和bottom偏移适合输入框靠近底部、页面结构不复杂的场景。不管哪种behavior前提都是能拿到键盘高度和窗口尺寸变化。RN内部靠的是Keyboard模块派发的keyboardWillShow、keyboardDidShow、keyboardWillHide、keyboardDidHide这些事件事件负载里的endCoordinates.height就是避让的依据。这条链路只要有一个环节事件没发出来KeyboardAvoidingView就成了摆设。2.2 RN on OpenHarmony的事件桥接存在明显的断点RN社区为OpenHarmony提供的适配层实现了RN核心框架的大部分能力但在键盘事件这块并不完整。iOS和Android上有系统级的键盘事件通知给到RN原生模块而OpenHarmony适配层早期版本对键盘事件的转发经常是缺失的或者只是零散地转发了一部分。我在实际调试时发现keyboardDidShow在部分版本里能触发但keyboardWillShow这种动画前事件基本靠不住导致JS侧永远在键盘完全弹起之后才知道有键盘避让动画自然跟不上。更麻烦的是KeyboardAvoidingView在计算避让高度时会拿窗口的宽高做差值。OpenHarmony窗口如果打开了沉浸式全屏布局窗口高度本身就不包含系统避让区域再加上软键盘是否占用布局空间的状态没有同步到RN侧JS计算的基准值就是错的。哪怕事件到了算出来的偏移量也不对。2.3 窗口高度信息不准确引发连锁反应RN在OpenHarmony上的根视图高度来源于原生窗口的布局参数。正常情况下键盘弹出且窗口设置为避让模式时系统会通过布局变化通知让根视图变矮RN内部重新测量JS侧的Dimensions.get(window).height会同步变小。但OpenHarmony适配层对这类布局更新事件的响应并不可靠导致RN根视图还是认为自己在全屏高度JS侧测量结果自然就失真了。于是你看到的结果就是键盘把系统的可绘制区域压缩了但RN并不知道窗口底层出现了空白的避让区而KeyboardAvoidingView又因为没有收到事件而没有任何动作所以页面既没有顶上去也没有缩短输入框被遮挡就是最终结果。2.4 综合来看三个环节各自缺了什么环节该干什么OpenHarmony上的实际表现OpenHarmony窗口层键盘弹出时调整窗口布局提供高度变化通知系统有避让模式但RN根视图不一定收到布局更新RN桥接层把原生键盘事件转发给JS侧事件转发链路不完整keyboardWillShow等事件经常缺失KeyboardAvoidingView靠事件驱动计算偏移量并应用布局收不到事件或拿到的数据不准避让逻辑整体失效所以单纯在JS层面给KeyboardAvoidingView换behavior参数是没用的因为它连子弹键盘事件都没拿到。要解决问题要么绕开事件链路直接在JS侧另想办法拿键盘高度要么把事件链路补上让KeyboardAvoidingView重新活过来。3. 不用改原生也能救急JS侧的键盘监听与手动避让组件先说结论如果你现在就是想把底部输入框从键盘底下捞出来最快、最稳妥的方式是放弃KeyboardAvoidingView自己在JS侧监听键盘事件手动管理底部偏移量。这个方案不用动原生代码改动集中在公共组件里App其他页面也能复用。3.1 用Keyboard模块监听键盘事件RN自带的Keyboard模块在OpenHarmony上不一定能触发所有事件但实测下来keyboardDidShow和keyboardDidHide的触发成功率要远高于keyboardWillShow。我们就以这两个事件作为数据源配合event.endCoordinates.height拿键盘高度。import { Keyboard, Platform } from react-native; const keyboardDidShowSub Keyboard.addListener(keyboardDidShow, (e) { const keyboardHeight e.endCoordinates?.height ?? 0; console.log(键盘弹出高度, keyboardHeight); }); const keyboardDidHideSub Keyboard.addListener(keyboardDidHide, () { console.log(键盘收起); }); // 组件卸载时记得移除监听这里有个细节部分OpenHarmony版本在事件对象里不保证有endCoordinates所以要用可选链兜底。如果拿不到键盘高度还可以退一步通过Dimensions取屏幕高度与可用高度的差值来估算但那个误差较大能不用就不用。3.2 封装一个自己的KeyboardAvoidingContainer我们要做的是把一个View组件的paddingBottom绑定到键盘高度上让底部内容被顶上去。为了避免多端行为不一致建议在iOS和Android上也统一用这套逻辑来走。import React, { useEffect, useState, useRef } from react; import { Keyboard, View, StyleSheet, Animated, Platform, } from react-native; function KeyboardAvoidingContainer({ children, offset 0, style }) { const [paddingBottom, setPaddingBottom] useState(0); useEffect(() { let showSub; let hideSub; // iOS 优先用 will 系列事件Android/OpenHarmony 用 did 事件兜底 const showEvent Platform.OS ios ? keyboardWillShow : keyboardDidShow; const hideEvent Platform.OS ios ? keyboardWillHide : keyboardDidHide; showSub Keyboard.addListener(showEvent, (e) { const height e.endCoordinates?.height ?? 0; // offset 用于补充底部安全区或额外间距 setPaddingBottom(height - offset 0 ? height - offset : height); }); hideSub Keyboard.addListener(hideEvent, () { setPaddingBottom(0); }); return () { showSub?.remove(); hideSub?.remove(); }; }, [offset]); return ( View style{[styles.flex, style, { paddingBottom }]} {children} /View ); } const styles StyleSheet.create({ flex: { flex: 1 }, }); export default KeyboardAvoidingContainer;这个容器组件的原理和KeyboardAvoidingView的behaviorpadding模式类似但它不依赖那个内部事件链路只认我们实际能收到的回调。实际操作中我把这个组件放进了项目的基础UI库所有聊天、评论、表单页面都统一引用效果立刻对齐了。3.3 页面有ScrollView时改成动态bottom方案如果页面底部输入框是悬浮在ScrollView之上的布局直接加paddingBottom会出现空白区域太大、列表内容没同步的问题。更好的做法是把整个页面包到这个容器里然后让ScrollView的底部跟着padding变化这样列表和输入框会像一个整体一样被顶起。还有个更简单的方式用Animated监听padding的动画值让避让过程平滑一点。别小看这个动画真实键盘弹出的瞬间页面如果哐当一下跳上去体验非常生硬。我后面直接改成Animated.timing驱动150到200毫秒的easeOut曲线观感好很多。const paddingAnim useRef(new Animated.Value(0)).current; function updatePadding(height) { Animated.timing(paddingAnim, { toValue: height, duration: 180, useNativeDriver: false, }).start(); } // 然后根容器使用 paddingAnim3.4 这个方案也有坑别和系统避让叠加最常踩的坑是某些OpenHarmony版本的应用窗口本来就设了键盘避让模式键盘弹出来时系统已经把窗口整体顶上去一段距离。此时如果你再在JS侧加一个同等高度的paddingBottom页面就会往上飞过头形成我之前说的双倍避让。解决办法是做一个避让责任方的约定。在你的RN页面根组件加载时先通过一个一次性开关比如全局变量或Context声明JS侧自行避让并在原生侧确认窗口不会被系统二次避让。如果你控制不了原生侧的窗口配置就在JS侧先做一次探测键盘弹出前后分别取Dimensions.get(window).height如果高度差大于0说明系统已经避让过了这时就不要再加等高的padding而是直接用差值减去这个系统避让高度。function measureWindowChange() { const before Dimensions.get(window).height; // 等键盘弹起后再取一次 return (after) { const diff before - after; setPaddingBottom(Math.max(0, keyboardHeight - diff)); }; }这个探测逻辑在多个版本上验证有效能够避免最让人头疼的顶飞问题。4. 治本把OpenHarmony原生窗口的避让能力接进RNJS侧方案是应急但如果你想在团队里建立一套长期稳定、键盘高度实时准确的解决方案还是得动一下原生侧把OpenHarmony窗口的键盘能力真正暴露给RN。4.1 原生侧先确认窗口布局和键盘避让模式在OpenHarmony的应用入口比如Ability或MainAbility对应的窗口那里需要检查窗口的布局设置。一般来说有两种工作模式系统自动避让窗口不设全屏布局系统会在键盘弹出时自动调整窗口内容的位置让焦点组件可见。这种模式下JS侧原则上不需要再做避让。全屏布局 开发者自行避让窗口设置了沉浸式全屏系统把整个屏幕都交给应用键盘弹出时应用需要自己计算键盘高度并布局内容。这种模式适合视频聊天、游戏、定制输入交互等场景。判断当前实际生效的是哪种模式可以在原生代码里打印窗口属性。如果你希望JS侧完全接管避让就把窗口设为全屏布局并关闭系统层面的键盘避让模式下对内容的强制位移这样RN就不会收到被系统动过的窗口高度所有紧凑都由JS统一算反而更可控。import { window } from kit.ArkUI; async function configureWindow() { const win window.getLastWindow(getContext(this)); // 全屏布局让 JS 侧全权负责避让 await win.setWindowLayoutFullScreen(true); // 再按需配置键盘避让模式为覆盖overlay而不压缩窗口 await win.setWindowKeyboardAvoidMode(window.WindowKeyboardAvoidMode.OVERLAY); }注意setWindowLayoutFullScreen和键盘避让模式的API命名和生效范围在不同OpenHarmony版本上有差异接入时以你使用的SDK版本文档为准。关键是你要明确到底由系统避让还是由应用避让二选一不能混着来。4.2 把原生键盘高度通过事件桥接喂给JS这是让KeyboardAvoidingView恢复元气的关键一步让RN侧能稳定收到键盘高度事件。OpenHarmony窗口对象提供了监听键盘高度变化的能力可以在原生侧注册一个回调把高度变化传给RN的EventEmitter然后JS侧复用Keyboard模块的频道发事件。// 原生侧ArkTS const win window.getLastWindow(getContext(this)); const onKeyboardHeightChange (height) { // 把高度派发给 JS这一步由 RN OH 桥接层封装 this.emitKeyboardEvent(keyboardDidShow, { endCoordinates: { height, screenX: 0, screenY: 0, width: 0 }, }); }; win.on(keyboardHeightChange, onKeyboardHeightChange);如果你们团队使用社区维护的RN OpenHarmony适配框架也可以直接在原生模块里实现一个Emitter常量JS侧通过NativeEventEmitter订阅完全不依赖RN自带的Keyboard模块。这样做的最大好处是事件触发时机比keyboardDidShow更贴近键盘动画开始时刻避让动画能做到跟手。4.3 事件时序键盘动画期间的高度更新节奏键盘不是瞬间弹出来的它会有一个从0到最终高度的动画过程。OpenHarmony的键盘高度变化事件会持续回调但回调频率随版本不同有波动。我实际记录过一组数据键盘弹出总耗时约240毫秒期间高度回调了约12次每次都带着最新的高度值。如果JS侧直接把每个高度值都setState会触发大量的重复渲染。建议在JS侧做一个轻量的节流或动画插值不要每次原生回调都直接驱动布局。可以使用一个Animated.Value原生回调时用Animated.timing过渡或者借助useRef记录最近一次高度只有变化超过3个像素才更新这样既能保持平滑又不至于性能崩掉。const lastHeight useRef(0); const KEYBOARD_EPSILON 3; function onKeyboardHeightChange(height) { if (Math.abs(height - lastHeight.current) KEYBOARD_EPSILON) return; lastHeight.current height; // 驱动避让 }4.4 兼容iOS和Android的封装原生桥接做好后JS侧不要直接依赖特定平台的监听而是封装一层统一API。我最后落地的方案是这样的优先用原生桥接的emitter接收键盘高度OpenHarmonyiOS保持系统自带Keyboard事件Android继续使用keyboardDidShow兜底。对外只暴露一个useKeyboardHeightHook页面组件全部通过这个钩子取键盘高度底层实现差异都被屏蔽掉。后续如果OpenHarmony适配层的键盘事件完善了只需要改这一层页面代码不用动。function useKeyboardHeight() { const [height, setHeight] useState(0); useEffect(() { // OpenHarmony 使用原生桥接 emitter if (Platform.OS harmony) { const emitter new NativeEventEmitter(KeyboardNative); const sub emitter.addListener(onKeyboardHeight, (e) { setHeight(e.height); }); return () sub.remove(); } // iOS / Android 使用系统事件 const showSub Keyboard.addListener( Platform.OS ios ? keyboardWillShow : keyboardDidShow, (e) setHeight(e.endCoordinates.height), ); const hideSub Keyboard.addListener(keyboardDidHide, () setHeight(0)); return () { showSub.remove(); hideSub.remove(); }; }, []); return height; }5. 不同页面结构踩过的坑与工程化建议键盘避让这件事没有一劳永逸的方案不同页面结构适合的避让策略完全不同。以下是我在实际适配中遇到的几类典型场景和对应解法希望能帮你少走弯路。5.1 底部聊天式输入框聊天、评论、弹幕这类页面输入框固定在底部上方是长列表。这类页面我最推荐全屏布局加JS侧自行避让因为聊天列表通常还需要配合倒序数据、回复定位、滚动跟随等操作如果系统擅自把窗口上移列表和输入框的相对关系会被打破。操作上把整个页面根容器放在我们前面写的KeyboardAvoidingContainer里列表区域flex: 1输入框区域固定在底部。键盘弹出时paddingBottom驱动输入框上移同时列表的高度被压缩视觉上就像输入框一直顶在键盘上沿体验非常接近原生输入体验。另外提醒一句如果聊天列表是类似微信那种气泡逆序布局避让后还要主动滚动到最后一条消息否则用户会看到一片空白。这个滚动到底的动作要在键盘高度变化之后再执行最好放在requestAnimationFrame或setTimeout里延后一帧。5.2 表单页 ScrollView表单页的特点是内容通常不满一屏用户输入时聚焦到哪个输入框哪个输入框就必须可见。这种场景下我建议优先让系统窗口自动避让而不是JS侧自算。因为系统避让能拿到焦点组件的位置自动上下滚动到可见区域比自己在JS里用ScrollView.scrollTo猜输入框坐标要靠谱得多。如果你坚持全屏布局加JS避让那就要手动管理ScrollView的滚动位置。做法是监听输入框的onFocus事件拿到相对页面的offsetY然后调用scrollTo把输入框顶到键盘上方减去一些安全间距。这个过程对键盘高度变化和布局变化非常敏感代码量大且容易出边界问题所以能交给系统就别自己扛。5.3 全屏弹窗 / ModalRN的Modal在OpenHarmony上表现有点特殊键盘弹出时Modal的避让行为经常跟主窗口不一致。我碰到过一次主窗口正常避让了但Modal里的输入框纹丝不动。排查下来发现问题是Modal创建时用了新的窗口或覆盖层原生配置的键盘避让模式没有同步过去。解决方法是在Modal内容的根组件上也套一层KeyboardAvoidingContainer让避让逻辑完全由JS侧负责。Modal容器因为天然是全屏覆盖JS侧给根View加paddingBottom是安全的不太会出现双倍避让问题。Modal visible{visible} transparent animationTypeslide KeyboardAvoidingContainer style{styles.modalWrap} TextInput placeholder弹窗里的输入 / /KeyboardAvoidingContainer /Modal5.4 组合拳SafeArea 键盘避让 滚动容器的叠用很多页面会同时用到SafeAreaView、KeyboardAvoidingView、ScrollView和FlatList叠在一起时就会出现混乱。核心原则同一时刻只让一个组件负责高度变化其他组件都基于调整后的可用高度来布局。我的建议是外层用SafeArea保证刘海屏安全区内层用KeyboardAvoidingContainer或KeyboardAvoidingView负责键盘避让最内层放ScrollView。避让组件不要嵌套多层否则每个组件都做一次paddingBottom高度就叠加爆了。你在检查布局时如果发现页面出现异常空白先怀疑是不是有两层避让逻辑同时生效。5.5 适配阶段的测试清单底部输入框弹出键盘确认输入框贴着键盘上沿无遮挡。收起键盘确认页面完全回到初始位置底部无残留空白。切换输入法的中英文、手写、语音模式确认键盘高度变化时避让跟随。在分屏模式下打开应用键盘行为是否和全屏一致。连续两次弹出键盘确认事件不会重复叠加。横屏状态下输入确认避让方向正确横屏键盘通常高度较小。这份清单我每次发版前都会过一遍尤其是横屏和分屏最容易出隐蔽问题。6. 最终方案矩阵与一点经验到了这一步其实已经可以做一个明确的选型了。我把不同方案整理成一张表方便你根据项目现状直接决策。方案改动范围稳定性适用场景KeyboardAvoidingView默认用法JS层零原生改动在OpenHarmony上基本不可用不推荐在鸿蒙上作为唯一方案JS侧键盘监听 手动paddingJS层零原生改动中高取决于事件能否触发应急、快速适配、页面不复杂原生窗口避让 KeyboardAvoidingView需改原生窗口配置高但受桥接事件完整性影响系统适配完善后的常规方案原生键盘高度桥接 JS手动避让需改原生模块和JS层最高完全可控大型应用、复杂页面、长期维护全屏布局 JS完全接管避让需改原生窗口配置最高聊天、视频、沉浸式布局页面个人建议如果团队是第一次接入OpenHarmony先走方案二把功能上线跑通观察几个版本后再逐步演进到方案四。一上来就做方案四原生桥接的调试成本不低而且OpenHarmony适配层迭代较快早期投入的桥接代码可能一升级就要重写。6.1 默认配置模板可以直接抄下面是我目前项目里使用的通用模板双端安全区、ScrollView、底部输入框都安排好了你复制过去改改样式就能跑。import React from react; import { SafeAreaView, ScrollView, TextInput, View, Text, StyleSheet, } from react-native; import KeyboardAvoidingContainer from ./KeyboardAvoidingContainer; function ChatLikeScreen() { return ( SafeAreaView style{styles.safeArea} KeyboardAvoidingContainer style{styles.flex} ScrollView style{styles.scroll} keyboardShouldPersistTapshandled Text style{styles.paragraph} 这里放消息列表或表单内容键盘弹出时会被正确顶起。 /Text /ScrollView View style{styles.bottomBar} TextInput style{styles.input} placeholder输入内容 placeholderTextColor#999 / /View /KeyboardAvoidingContainer /SafeAreaView ); } const styles StyleSheet.create({ safeArea: { flex: 1, backgroundColor: #fff }, flex: { flex: 1 }, scroll: { flex: 1 }, paragraph: { padding: 16, lineHeight: 22 }, bottomBar: { flexDirection: row, alignItems: center, paddingHorizontal: 12, paddingVertical: 8, borderTopWidth: StyleSheet.hairlineWidth, borderTopColor: #e5e5e5, }, input: { flex: 1, height: 40, borderRadius: 18, backgroundColor: #f5f5f5, paddingHorizontal: 16, }, }); export default ChatLikeScreen;6.2 跨版本兼容的记忆点OpenHarmony的版本更新节奏比传统移动平台更快RN适配层也在不断补齐能力。我经历过一次系统升级后原先缺失的键盘事件突然能触发了但同一套代码在旧版本上又没有任何反应。后来我养成了一个习惯在公共避让组件里加上事件触发的埋点日志一旦发现某个版本的行为变化能立刻定位。这个日志平时关掉排查问题时打开成本极低但收益很大。再补充一个小技巧在真机调试OpenHarmony键盘问题时不要只看法式测试要连上调试工具看系统窗口的布局状态。键盘弹出后窗口高度是变矮了还是没变这个信息能直接告诉你该让系统避让还是JS接管比反复猜测高效得多。6.3 我的一点体会键盘避让这种问题看起来只是一个小交互实际上牵涉到的层级比想象中深。我一开始也是一味地用KeyboardAvoidingView换参数试来试去浪费了不少时间后来沉下心把iOS、Android、OpenHarmony三套系统的差异理了一遍才发现核心就是事件到不到位、窗口高度准不准这两件事。把这两点抓稳了方案自然就浮出水面。希望这篇对正在做RN鸿蒙适配的你有点帮助照着方案落地键盘那点事基本就能收工了。