【HarmonyOS Next】鸿蒙应用实现弹框 DialogHub 详解
- 2025-03-24  上海
- 本文字数:3630 字 - 阅读完需:约 12 分钟 

【HarmonyOS Next】鸿蒙应用实现弹框 DialogHub 详解
一、前言
鸿蒙中实现弹框目前官方提供 openCustomDialog 和 CustomDialog 两种模式。推荐前者,详情见下图和官网文档链接:
 
 https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V14/arkts-uicontext-custom-dialog-V14UI 强绑定的实现方式 API 已标注不推荐。推荐使用 UI 框架层预留挂靠节点的方式,即 openCustomDialog。
这两者的差别详见【HarmonyOS Next】鸿蒙应用弹框和提示气泡详解(一)
除此之外开源三方库 DialogHub 可以更加快捷的使用弹窗:
 
 https://gitee.com/hadss/dialoghub
DialogHub 底层实现原理为,使用浮层 OverlayManager➕半模态页面 bindSheet 来实现弹框。可以达到我们在传统 Android 和 IOS 开发中,弹框与页面生命周期绑定的效果(页面隐藏,弹框隐藏。页面销毁,弹框销毁)
DialogHub 接口属性详细信息如下:https://gitee.com/hadss/dialoghub/blob/master/docs/Reference.md
 
 二、DialogHub 的使用
目前 DialogHub 还是 RC 版本,并非 Final 版本。请谨慎使用。
目前 DialogHub 可以实现的弹框效果如下:
 
 使用起来很简单,通过三方库通过级联的方式,获取弹框实例对象,设置弹框的样式,布局,和弹框上的属性。甚至连弹框内容模板的设置和数据的更新也通过级联属性设置,这个思路不错。
// 导依赖包之后就可操作DialogHub对象import {  DialogHub} from "@hadss/dialoghub"
 
 如图所示,红框中提供了默认的三种样式的弹框。以 Toast 弹框举例:
  showToastTest(){    DialogHub.getToast()      .setContent(wrapBuilder(TextToastBuilder))        // 自定义内容                .setConfig(CommonConstant.CUSTOM_SAMPLE_CONFIG)        // 持续时间            .setDuration(CommonConstant.DURATION_3000)      .build()      .show();
  }
  // 布局的内容  @Builder  TextToastBuilder() {    Stack() {      Text("测试文本")        .fontColor(Color.Black)        .fontSize(52)    }    .padding({ left: 20, right: 20 })    .height(100)  }
自定义弹框:
        this.specifiedLocationDialog = this.specifiedLocationDialog ?? DialogHub.getCustomDialog()                      .setOperableContent(wrapBuilder(SnackbarBuilder), (action: DialogAction) => {                        let param = new SnackbarParams(() => {                          action.dismiss()                        }, this.pageInfos)                        return param                      })                      // DocsDot                      .setStyle({                        radius: $r('app.float.custom_template_sample_radius'),                        shadow: CommonConstant.CUSTOM_SAMPLE_STYLE_SHADOW                      })                      // DocsDot                      .setConfig({                        dialogBehavior: { isModal: false, passThroughGesture: true },                        dialogPosition: {                          alignment: DialogAlignment.Bottom,                          offset: { dx: 0, dy: $r('app.float.specified_location_offset') }                        }                      })                      .build();                    this.specifiedLocationDialog.show();
更新弹框内容:
   let intervalID: number = -1;                    let time: number = CommonConstant.TIMED_DIALOG_DURATION;                    let params: TimeToastParams =                      new TimeToastParams(CommonConstant.TIMED_DIALOG, time + CommonConstant.TIMED_CLOSED);                    // DocsCode 5                    this.intervalsDisappearsDialog = this.intervalsDisappearsDialog ?? DialogHub.getCustomDialog()                      .setContent(wrapBuilder(TimeToastBuilder), params)                      .setStyle({                        radius: $r('app.float.popup_disappears_intervals_radius'),                        shadow: CommonConstant.CUSTOM_SAMPLE_STYLE_SHADOW                      })                      .setAnimation({ dialogAnimation: AnimationType.UP_DOWN })                      .setConfig({                        dialogBehavior: { isModal: false, passThroughGesture: true },                        dialogPosition: {                          alignment: DialogAlignment.Top,                          offset: { dy: $r('app.float.popup_disappears_intervals_offset'), dx: 0 }                        }                      })                      .build();
                    this.intervalsDisappearsDialog.show();
                    intervalID = setInterval(() => {                      time -= 1;                      params.content = time + CommonConstant.TIMED_CLOSED;                      this.intervalsDisappearsDialog?.updateContent(params)                      if (time <= 0 && intervalID) {                        this.intervalsDisappearsDialog?.dismiss();                        clearInterval(intervalID);                      }                    }, CommonConstant.DURATION_1000);
三、源码示例
首先配置依赖:
{  "modelVersion": "5.0.0",  "description": "Please describe the basic information.",  "dependencies": {    "@hadss/dialoghub": "^1.0.0-rc.1"  },  "devDependencies": {    "@ohos/hypium": "1.0.19",    "@ohos/hamock": "1.0.0"  },  "dynamicDependencies": {}}
之后导入包,进行调用:
import { DialogHub } from '@hadss/dialoghub';import { getContext } from '@ohos.app.ability';import CommonConstant from '../utils/CommonConstant';
// 假设的 TextToastParams 类型interface TextToastParams {    title?: string;}
// TextToastBuilder 构建器函数@Builderexport function TextToastBuilder(param: TextToastParams) {    Stack() {        Text(param?.title ?? CommonConstant.PURE_TEXT)           .fontColor($r('app.color.item_text_color'))           .fontSize($r('app.float.font_size_regular'))    }   .padding({ left: $r('app.float.text_toast_padding'), right: $r('app.float.text_toast_padding') })   .height($r('app.float.text_toast_height'))}
// 假设的组件扩展,用于按钮样式@Extend(Button)function superFancyButton() {    return this       .width(CommonConstant.FULL_LENGTH)       .height($r('app.float.index_action_height'))       .margin({ bottom: $r('app.float.index_action_margin') })       .fontSize($r('app.float.font_size_medium'))       .fontWeight(FontWeight.Medium)       .backgroundColor($r('app.color.base_blue'));}
@Entry@Componentstruct DialogHubExample {    // 获取 UI 上下文    getUIContext() {        return getContext();    }
    aboutToAppear(): void {        // 初始化 DialogHub        DialogHub.init(this.getUIContext());        // 开启日志        DialogHub.openLog('DEBUG');
        // 创建自定义模板        DialogHub.createCustomTemplate(CommonConstant.CUSTOM_TEMPLATE_SIMPLE)           .setContent(wrapBuilder(TextToastBuilder))           .setStyle({ backgroundColor: Color.White })           .setConfig({ dialogBehavior: { passThroughGesture: true, isModal: false } })           .register();    }
    showCustomDialog() {        // 显示自定义模板的弹框        DialogHub.show({            templateName: CommonConstant.CUSTOM_TEMPLATE_SIMPLE,            data: {                // 传递数据给弹框                title: '这是自定义弹框的标题'            }        });    }
    build() {        Column({ space: 20 }) {            Button('显示自定义弹框', { stateEffect: true, type: ButtonType.Capsule })               .superFancyButton()               .onClick(() => {                    this.showCustomDialog();                });        }       .width('100%')       .height('100%')       .padding({ top: 20, bottom: 20, left: 20, right: 20 });    }}
版权声明: 本文为 InfoQ 作者【GeorgeGcs】的原创文章。
原文链接:【http://xie.infoq.cn/article/069b610b4cd4230a8519a6961】。文章转载请联系作者。

GeorgeGcs
路漫漫其修远兮,吾将上下而求索。 2024-12-24 加入
历经腾讯,宝马,研究所,金融。 待过私企,外企,央企。 深耕大应用开发领域十年。 OpenHarmony,HarmonyOS,Flutter,H5,Android,IOS。 目前任职鸿蒙应用架构师。 HarmonyOS官方认证创作先锋







 
    
 
				 
				 
			


评论