HarmonyOS 鸿蒙Next中如何主动的关闭键盘、弹框,通用方法

HarmonyOS 鸿蒙Next中如何主动的关闭键盘、弹框,通用方法 在App中,可能会存在不同的页面中进行弹框,或者正在输入的情况。

当有一些外部的事件,需要关闭当前的弹框或输入态。

想问一下有没有什么通用的方法可以实现上述的能力,而不是每个页面都需要适配关闭弹框,或输入法面板

3 回复

【背景知识】 使用弹窗组件时,可优先考虑自定义弹窗,便于自定义弹窗的样式与内容。通过CustomDialogController类显示自定义弹窗,不支持直接在类中定义和使用。通常需要将弹框逻辑封装成Builder或其他组件,以便在需要时调用。

【解决方案】 解决方案一:使用Builder封装自定义弹框。

@CustomDialog
struct CustomDialogExample {
  textContent: string = ""
  dialogController: CustomDialogController = new CustomDialogController({
    builder: CustomDialogExample({ textContent: this.textContent }),
  })

  build() {
    Column() {
      Text(this.textContent)
        .fontSize(20)
        .margin({ top: 10, bottom: 10 })
    }
  }
}

@Entry
@Component
struct Index {
  @Builder
  ButtonShowToast(buttonText: string, content: string) {
    Button(buttonText)
      .onClick(() => {
        let dialogController: CustomDialogController = new CustomDialogController({
          builder: CustomDialogExample({ textContent: content }),
        })
        dialogController.open()
      })
  }

  build() {
    Row() {
      Column() {
        this.ButtonShowToast('test1', '111')
        this.ButtonShowToast('test2', '222')
      }
    }
  }
}

解决方案二:使用PromptAction能力,参考文档:openCustomDialog。示例代码如下:

import { PromptAction } from '@ohos.arkui.UIContext';
import { ComponentContent } from '@kit.ArkUI';
import { buildText } from './MyDialog';

@Entry
@Component
struct Index {
  private uiContext: UIContext = this.getUIContext()
  private promptAction: PromptAction = this.uiContext.getPromptAction();

  build() {
    Column() {
      Button("click me!!!!!!!!!!")
        .width('50%')
        .type(ButtonType.Capsule)
        .backgroundColor(Color.Orange)
        .onClick(() => {
          // 打开全局自定义弹窗
          let contentNode = new ComponentContent(this.uiContext, wrapBuilder(buildText));
          this.promptAction.openCustomDialog(contentNode)
        })
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}
@CustomDialog
@Component
export struct MyDialog {
  controller?: CustomDialogController;

  build() {
    Column() {
      Button("click me!")
        .width('50%')
        .type(ButtonType.Capsule)
        .backgroundColor(Color.Orange)
    }
    .width('100%')
    .height('70%')
    .justifyContent(FlexAlign.Center)
    .backgroundColor(Color.Blue)
    .opacity(0.5)
  }
}

@Builder
export function buildText() {
  MyDialog()
}

解决方案三:

  • 通过GlobalDialogController单例统一管理弹窗。
// 单例模式类,用于管理全局弹窗控制器。
class GlobalDialogController {
  _dialogController?: CustomDialogController | null
  public static instance: GlobalDialogController | null;

  public static getInstance(): GlobalDialogController {
    if (!GlobalDialogController.instance) {
      GlobalDialogController.instance = new GlobalDialogController();
    }
    return GlobalDialogController.instance;
  }
}

完整示例代码如下:

// 单例模式类,用于管理全局弹窗控制器。
class GlobalDialogController {
  _dialogController?: CustomDialogController | null
  public static instance: GlobalDialogController | null;

  public static getInstance(): GlobalDialogController {
    if (!GlobalDialogController.instance) {
      GlobalDialogController.instance = new GlobalDialogController();
    }
    return GlobalDialogController.instance;
  }
}

@Entry
@Component
struct Index {
  controller: GlobalDialogController = GlobalDialogController.getInstance()

  build() {
    Row() {
      Column({ space: 20 }) {
        Button('Toast显示')
          .onClick(() => {
            // 调用GlobalDialog组件showDialog方法打开弹窗
            new GlobalDialog().showDialog('loading。。。', this.controller)

            setTimeout(() => {
              new GlobalDialog().hide()
            }, 2000)
          })
      }
      .width('100%')
    }
    .height('100%')
  }
}

@Component
export struct GlobalDialog {
  // 传入instance实例并打开弹窗
  showDialog(
    msg: string,
    instance: GlobalDialogController,
    _cancelCallBack?: () => void,
  ): void {
    this.hide()
    if (instance) {
      instance._dialogController = new CustomDialogController({
        builder: _GlobalDialog({ msg: msg }),
        autoCancel: false,
        cancel: () => {
          instance._dialogController = null
          if (_cancelCallBack) {
            _cancelCallBack()
          }
        },
        customStyle: true,
        alignment: DialogAlignment.Center,
        maskColor: 0x33000000,
      })
      instance._dialogController.open()
    }
  }

  // 关闭弹窗
  async hide() {
    const controller = GlobalDialogController.instance?._dialogController;
    if (controller) {
      await controller.close();
      GlobalDialogController.instance!._dialogController = null;
    }
  }

  aboutToDisappear(): void {
    // 清空实例,防止组件销毁后内存泄漏。
    GlobalDialogController.instance = null
  }

  build() {
  }
}

@CustomDialog
struct _GlobalDialog {
  controller: CustomDialogController
  close: () => void = () => {
  }
  @State msg: string = ""

  build() {
    Column() {
      Text(this.msg)
        .fontColor(Color.White)
    }
    .justifyContent(FlexAlign.Center)
    .alignItems(HorizontalAlign.Center)
    .padding(12)
    .margin(30)
    .borderRadius(10)
    .backgroundColor(Color.Black)
  }
}

更多关于HarmonyOS 鸿蒙Next中如何主动的关闭键盘、弹框,通用方法的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS Next中,可通过调用hide()方法主动关闭键盘或弹框。对于键盘,使用inputMethodManager.hideSoftInput();对于弹框,直接调用其hide()方法。此方式适用于系统标准组件,无需依赖Java或C语言。

在HarmonyOS Next中,可以通过统一的焦点管理机制实现键盘和弹框的通用关闭。使用FocusManagerclearFocus()方法可以主动移除当前焦点,从而自动关闭键盘。对于弹框,建议通过全局事件总线发布关闭事件,各弹框组件订阅该事件并自行处理关闭逻辑。这种方式无需在每个页面单独适配,只需在应用初始化时注册相应的事件监听即可。

回到顶部