嵌入页面切回来,键盘为什么不再自己弹出:HarmonyOS 7 把焦点先留在根容器

搜索面板嵌在 EmbeddedComponent 中。旧版本从详情页返回时,第一个 TextInput 会自动拿到焦点并拉起键盘;升级后键盘不弹了,开发者第一反应是“输入框失效”。其实 API 26 统一了层级页面切换时的焦点规则:未设置 defaultFocus、也没主动 requestFocus 时,焦点停在根容器,不再自动下发给第一个可获焦子节点。

新规则减少了意外弹键盘,但也会暴露那些把“第一个控件刚好是输入框”当成产品逻辑的页面。

验证边界:本文依据华为 2026-08-19 更新的 HarmonyOS 7(API 26)Beta1 行为变更说明。示例中的判定与状态模型已在宿主 Node.js 环境跑过断言;平台组件接入片段未在 API 26 SDK 或真机编译运行,不能替代目标设备验收。

EmbeddedComponent焦点决策流程

两种进入方式不要混在一起

场景API 26 行为是否应显式聚焦
外部走焦进入 EmbeddedUIExtensionAbility正常下发到首个可获焦节点按交互设计决定
层级页面切换后焦点转入默认停留根容器需要自动输入时才设置

案例一:扫码结果页返回搜索页

返回后立即弹键盘可能遮住扫码结果,因此应该保留根容器焦点,让用户点输入框时再进入编辑。把意图写成状态,不依赖组件顺序:

type FocusIntent = 'preserve-root'|'resume-editor'|'user-request';
function shouldRequestInput(intent: FocusIntent, pageVisible: boolean, dialogOpen: boolean): boolean {
  return pageVisible && !dialogOpen && (intent === 'resume-editor' || intent === 'user-request');
}
if (shouldRequestInput('preserve-root', true, false)) throw new Error('must not pop keyboard');
if (!shouldRequestInput('resume-editor', true, false)) throw new Error('resume should focus');

案例二:收银台回到验证码输入

用户刚从协议页返回,业务明确要求继续输入,此时可给目标 TextInput 设置稳定 id,在页面状态恢复完成后 requestFocus。不要用固定延时赌页面已经挂载。

type PageState = { appeared: boolean; restored: boolean; targetId?: string };
function focusTarget(state: PageState): string | null {
  if (!state.appeared || !state.restored) return null;
  return state.targetId ?? null;
}
if (focusTarget({appeared:true,restored:false,targetId:'codeInput'}) !== null) throw new Error('too early');
if (focusTarget({appeared:true,restored:true,targetId:'codeInput'}) !== 'codeInput') throw new Error('target');

平台页面中可以选择 .defaultFocus(true),也可以在 onAppear 后通过 FocusController.requestFocus(id) 主动请求。两者都应服务于明确交互,不要同时设置造成抢焦点。

还要检查哪些副作用

焦点变化会影响键盘、屏幕朗读、遥控器/键盘导航和焦点样式。验收时记录“焦点在哪个节点”,不能只记录键盘是否出现。弹窗、菜单打开时也不要把焦点强行拉回输入框。

发布前清单

  • 为自动聚焦写出产品理由,而不是恢复旧行为。
  • 目标节点使用稳定 id,页面销毁后取消延迟任务。
  • 返回、外部走焦、首次进入分别测试。
  • 覆盖键盘、无障碍和方向键操作。
  • 在 API 26 目标设备验证真实焦点链。

官方依据

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐