HarmonyOS鸿蒙Next中输入框自动失焦问题
HarmonyOS鸿蒙Next中输入框自动失焦问题 使用输入框拉起系统键盘后,总会出现莫名其妙的突然失焦导致系统键盘掉落,该如何解决
应该是弹出的toast获焦了,导致输入框失焦键盘收起。
更多关于HarmonyOS鸿蒙Next中输入框自动失焦问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
开发者你好,自定义弹窗可以参考下3楼下的回复,或者参考下以下示例通过openCustomDialog创建自定义弹窗:
【背景知识】
- [@Builder装饰器](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-builder):@Builder装饰的函数也称为“自定义构建函数”。
- wrapBuilder:可以使用wrapBuilder封装全局@Builder。
- openCustomDialog:创建并弹出dialogContent对应的自定义弹窗。
- @Builder装饰器修饰函数不支持传递函数方法,仅支持传值,有按值传递和按引用传递两种。但可以通过WrappedBuilder包装类将@Builder的函数包装,之后将WrappedBuilder对象当作变量进行传递。
开发步骤如下:
- 自定义控制器类,用于创建弹窗、打开弹窗、更新弹窗内容、关闭弹窗等操作。
class CustomDialogController {
private uiContext: UIContext
private promptDialog: PromptAction
private contentNode: ComponentContent<object>
params?: Params
constructor(uiContext: UIContext, builder: WrappedBuilder<[]>, params?: Params) {
this.uiContext = uiContext
this.promptDialog = this.uiContext.getPromptAction()
this.params = params
this.contentNode = new ComponentContent(this.uiContext, builder, this)
}
openDialog() {
this.promptDialog.openCustomDialog(this.contentNode)
}
closeDialog() {
this.promptDialog.closeCustomDialog(this.contentNode)
}
updateDialogContent(params: Params) {
this.params = params
this.contentNode.update(this)
}
}
- 自定义@Builder,用于显示自定义弹窗内容,更新弹窗内容,关闭弹窗。
[@Builder](/user/Builder)
function dialogBuilder(controller?: CustomDialogController) {
Column() {
Text(`${controller!.params?.content}`)
Button('更新弹框内容').onClick(() => {
controller!.updateDialogContent(new Params('弹框内容已更新'))
})
Button('关闭弹窗').onClick(() => {
controller!.closeDialog()
})
}.height(200).width('100%').backgroundColor(Color.Pink)
}
- 页面初始化弹窗控制器并使用。
@Entry
@Component
struct CustomDialogPage {
uiContext = this.getUIContext();
private customDialogController: CustomDialogController =
new CustomDialogController(this.getUIContext(), wrapBuilder(dialogBuilder), new Params('这是一个自定义的弹框'))
build() {
Column() {
Button('open dialog')
.fontWeight(FontWeight.Bold)
.onClick(() => {
this.customDialogController!.openDialog()
})
}
.alignItems(HorizontalAlign.Center)
.justifyContent(FlexAlign.Center)
.width('100%')
.height('100%')
}
}
完整代码如下:
import { ComponentContent, PromptAction } from '@kit.ArkUI'
class Params {
content: string
constructor(content: string) {
this.content = content
}
}
class CustomDialogController {
private uiContext: UIContext
private promptDialog: PromptAction
private contentNode: ComponentContent<object>
params?: Params
constructor(uiContext: UIContext, builder: WrappedBuilder<[]>, params?: Params) {
this.uiContext = uiContext
this.promptDialog = this.uiContext.getPromptAction()
this.params = params
this.contentNode = new ComponentContent(this.uiContext, builder, this)
}
openDialog() {
this.promptDialog.openCustomDialog(this.contentNode)
}
closeDialog() {
this.promptDialog.closeCustomDialog(this.contentNode)
}
updateDialogContent(params: Params) {
this.params = params
this.contentNode.update(this)
}
}
@Entry
@Component
struct CustomDialogPage {
uiContext = this.getUIContext();
private customDialogController: CustomDialogController =
new CustomDialogController(this.getUIContext(), wrapBuilder(dialogBuilder), new Params('这是一个自定义的弹框'))
build() {
Column() {
Button('open dialog')
.fontWeight(FontWeight.Bold)
.onClick(() => {
this.customDialogController!.openDialog()
})
}
.alignItems(HorizontalAlign.Center)
.justifyContent(FlexAlign.Center)
.width('100%')
.height('100%')
}
}
[@Builder](/user/Builder)
function dialogBuilder(controller?: CustomDialogController) {
Column() {
Text(`${controller!.params?.content}`)
Button('更新弹框内容').onClick(() => {
controller!.updateDialogContent(new Params('弹框内容已更新'))
})
Button('关闭弹窗').onClick(() => {
controller!.closeDialog()
})
}.height(200).width('100%').backgroundColor(Color.Pink)
}
希望HarmonyOS能继续推出更多实用的功能,满足用户的不同需求。
请问该怎么解决,就是在发布完成后会弹一个3秒的toast,在这3秒内再次拉起输入框然后3秒后toast消失输入框也不会失焦
有没有demo? 我这边测试是没有问题的
我的这个输入框发布完内容后会弹一个toast提示,在toast展示期间再次拉起输入框后等toast消失就会使输入框失焦,如果在toast消失后拉起就不会突然失焦,请问该如何解决
开发者你好,一般被动走焦是组件焦点因系统或其他操作而自动转移,是焦点系统的默认行为,参考链接:走焦规范。开发者不希望toast上获取焦点可以设置组件不能获取焦点focusable(false),焦点就不会被转移此组件上,参考链接:focusable。同时可以通过requestFocus(true)主动让焦点转移至参数指定的组件上,参考链接:requestFocus。
开发者可以参考下以下示例防止输入框失焦:
在loading自定义弹窗的最外层的组件添加focusable(false),设置loading自定义弹窗组件不可以获焦,键盘也不会自动收起。但输入框还是会失焦,导致光标消失,使用onBlur事件监听失焦事件,触发失焦则执行requestFocus方法,使输入框重新获焦。 代码示例如下:
- LoadingManager.ets,定义loading工具类。
import { promptAction, window } from "@kit.ArkUI";
let windowClass: window.Window | undefined = AppStorage.get('windowClass');
let dialogHeight: number = 0;
class LoadingManager {
customDialogId: number | undefined = undefined;
public static createOption(builder: CustomBuilder) {
const option: promptAction.CustomDialogOptions = {
builder: builder,
alignment: DialogAlignment.Center,
cornerRadius: 0,
width: "110%",
height: dialogHeight,
backgroundBlurStyle: BlurStyle.NONE,
};
return option;
}
show(context: Object, uiContext: UIContext, height: number) {
dialogHeight = height;
uiContext.getPromptAction().showToast({ message: "用户名或密码错误" });
if (windowClass) {
windowClass.setSpecificSystemBarEnabled('status', false)
.then(() => {
console.info('Succeeded in setting the status bar to be invisible.');
})
.catch(() => {
});
}
uiContext.getPromptAction()
.openCustomDialog(LoadingManager.createOption(Loading.bind(context)))
.then((dialogId: number) => {
this.customDialogId = dialogId;
});
}
hide(uiContext: UIContext) {
if (this.customDialogId) {
uiContext.getPromptAction().closeCustomDialog(this.customDialogId);
if (windowClass) {
windowClass.setSpecificSystemBarEnabled('status', true)
.then(() => {
console.info('Succeeded in setting the status bar to be invisible.');
})
.catch(() => {
});
}
}
}
}
@Builder
function Loading() {
Column() {
LoadingProgress()
.width(50).height(50)
.color(Color.White);
}
.focusable(false) // 设置当前组件不可以获焦
.width('100%')
.height('100%')
.backgroundColor('rgba(0,0,0,0.5)')
.justifyContent(FlexAlign.Center);
}
export default new LoadingManager();
- Index.ets中调用。
import LoadingManager from './LoadingManager';
import { display } from '@kit.ArkUI';
@Entry
@Component
struct Index {
@State phoneNumber: string = '';
@State displayHeight: number = 0;
// 模拟接口loading
mockRequest() {
LoadingManager.show(this, this.getUIContext(), this.displayHeight);
setTimeout(() => {
LoadingManager.hide(this.getUIContext());
}, 2000);
}
aboutToAppear() {
this.displayHeight = this.getUIContext().px2vp(display.getDefaultDisplaySync().height);
}
build() {
RelativeContainer() {
TextInput({ placeholder: '请输入手机号', text: this.phoneNumber })
.margin({ top: 55,left:16,right:16 })
.id("key2")
.type(InputType.Number)
.onChange((value: string) => {
this.phoneNumber = value;
if (this.phoneNumber.length === 11) {
this.mockRequest();
}
})
.onFocus(() => {
setTimeout(() => {
this.phoneNumber = '';
}, 2100); // 模拟loading后删除号码
})
.onBlur(() => { // 失焦触发
focusControl.requestFocus('key2'); // 重新获焦
});
}
.height('100%')
.width('100%');
}
}
若开发者非此场景,为了进一步分析还请开发者提供一个可以复现问题的demo以及您的设备版本信息,谢谢了。
加个软键盘隐藏监听,如果当前是焦点状态就弹出软键盘。
有时候语音转换文字都是重复转换 ,然后发出键也没有了,
鸿蒙Next中Input组件自动失焦通常由焦点管理冲突引起。可能原因包括:页面中存在多个可聚焦组件时焦点竞争;组件属性focusable设置不当;或页面快速刷新导致焦点丢失。检查代码中是否误设了其他组件的requestFocus或onBlur回调。
在HarmonyOS Next中,输入框自动失焦通常与焦点管理或组件生命周期有关。以下排查方向供参考:
-
检查焦点竞争:确认页面内是否有其他可获焦组件(如另一个输入框、按钮)在键盘拉起时意外获得了焦点。可尝试暂时隐藏其他可获焦元素进行验证。
-
审查组件状态:若输入框在
aboutToAppear或aboutToDisappear等生命周期函数中触发了状态重置(如清空内容),可能间接导致失焦。确保状态变更不会在输入过程中意外执行。 -
规避异步操作干扰:键盘拉起后,若存在异步任务(如网络请求、定时器)强制刷新UI或重新绑定数据,可能打断焦点。建议将这类操作与用户输入时序解耦。
-
验证布局稳定性:动态布局变化(如键盘弹起触发页面伸缩)可能引起组件重建。可通过设置固定布局或使用
position: fixed减少布局抖动。 -
使用焦点锁定:对于需持续保持焦点的场景,可通过
focusControl.requestFocus主动管理焦点,并在输入完成前阻止焦点转移。
可优先从焦点竞争和生命周期入手,多数异常失焦与此相关。若问题仍存,建议提供最小化复现代码片段以便进一步分析。

