HarmonyOS鸿蒙Next中输入框自动失焦问题

HarmonyOS鸿蒙Next中输入框自动失焦问题 使用输入框拉起系统键盘后,总会出现莫名其妙的突然失焦导致系统键盘掉落,该如何解决

11 回复

应该是弹出的toast获焦了,导致输入框失焦键盘收起。

更多关于HarmonyOS鸿蒙Next中输入框自动失焦问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


开发者你好,自定义弹窗可以参考下3楼下的回复,或者参考下以下示例通过openCustomDialog创建自定义弹窗:

【背景知识】

开发步骤如下:

  1. 自定义控制器类,用于创建弹窗、打开弹窗、更新弹窗内容、关闭弹窗等操作。
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)
  }
}
  1. 自定义@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)
}
  1. 页面初始化弹窗控制器并使用。
@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方法,使输入框重新获焦。 代码示例如下:

  1. 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();
  1. 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中,输入框自动失焦通常与焦点管理或组件生命周期有关。以下排查方向供参考:

  1. 检查焦点竞争:确认页面内是否有其他可获焦组件(如另一个输入框、按钮)在键盘拉起时意外获得了焦点。可尝试暂时隐藏其他可获焦元素进行验证。

  2. 审查组件状态:若输入框在aboutToAppearaboutToDisappear等生命周期函数中触发了状态重置(如清空内容),可能间接导致失焦。确保状态变更不会在输入过程中意外执行。

  3. 规避异步操作干扰:键盘拉起后,若存在异步任务(如网络请求、定时器)强制刷新UI或重新绑定数据,可能打断焦点。建议将这类操作与用户输入时序解耦。

  4. 验证布局稳定性:动态布局变化(如键盘弹起触发页面伸缩)可能引起组件重建。可通过设置固定布局或使用position: fixed减少布局抖动。

  5. 使用焦点锁定:对于需持续保持焦点的场景,可通过focusControl.requestFocus主动管理焦点,并在输入完成前阻止焦点转移。

可优先从焦点竞争和生命周期入手,多数异常失焦与此相关。若问题仍存,建议提供最小化复现代码片段以便进一步分析。

回到顶部