《HarmonyOSNext弹窗:ComponentContent动态玩转企业级弹窗》
·
《HarmonyOSNext弹窗:ComponentContent动态玩转企业级弹窗》
##Harmony OS Next ##Ark Ts ##教育
本文适用于教育科普行业进行学习,有错误之处请指出我会修改。
🚫 为啥要抛弃CustomDialogController?
传统CustomDialogController
简直像块木头!🤖 不能动态创建、不支持实时刷新,在复杂场景里卡到窒息!救星来了——用UIContext
家的PromptAction.openCustomDialog()
,丝滑到飞起!✈️
🎨 两种姿势玩转openCustomDialog
传参方式 | 灵活性 | UI耦合度 | 适用场景 | 动态更新支持 |
---|---|---|---|---|
ComponentContent 🧩 |
⭐⭐⭐⭐⭐ | 解耦! | 高度定制化弹窗 | ✅ 可用updateCustomDialog |
Builder 🔗 |
⭐⭐ | 绑定上下文 | 想用系统默认风格的懒人模式 | ❌ 不支持 |
💡 本文重点讲解
ComponentContent
玩法! Builder党请移步👉openCustomDialog
文档
🎭 弹窗模式自由切换
调参小能手isModal
:
// true:霸道总裁模态框(必须处理才能点别处)
// false:佛系非模态框(随便点不拦你)
{ isModal: true }
⏳ 弹窗生命周期全监控
弹窗从生到死全记录📝:
1️⃣ onWillAppear
→ 2️⃣ onDidAppear
→ 3️⃣ onWillDisappear
→ 4️⃣ onDidDisappear
像追剧一样掌控每个节点!📺
🪄 弹窗操作三连击
🔮 STEP 1:创建ComponentContent
private contentNode = new ComponentContent(
this.ctx,
wrapBuilder(buildText), // 🧱 封装自定义组件
new Params(this.message) // 🎁 传参可缺省
);
📌 注意:
Params
能传基础数据类型
🚪 STEP 2:开窗!
// 默认开启完全自定义样式(customStyle=true)
PromptActionClass.ctx.getPromptAction()
.openCustomDialog(contentNode, options)
.then(() => console.info('弹窗出道成功!🎉'))
.catch((error: BusinessError) => {
console.error(`翻车代码${error.code}|原因:${error.message}💥`);
});
✋ STEP 3:关窗+清理内存
PromptActionClass.ctx.getPromptAction()
.closeCustomDialog(contentNode)
.then(() => {
console.info('弹窗杀青~👋');
contentNode?.dispose(); // ♻️ 内存清理必做!
})
.catch((error: BusinessError) => { ... }); // 同上
⚠️ 重点:在弹窗内关闭需封装静态方法(参考下文完整代码)
🔄 动态更新双攻略
📢 更新内容
this.contentNode.update(new Params('新鲜内容')); // 秒变文案!
🎛️ 更新属性
// 支持属性:alignment|offset|autoCancel|maskColor
PromptActionClass.ctx.getPromptAction()
.updateCustomDialog(contentNode, {
alignment: DialogAlignment.Bottom // 立刻沉底!
});
💣 巨坑预警:未设置的属性会变回默认值!
例:初始设置{ alignment: Top, offset: {dx:0,dy:50} }
→ 更新{ alignment: Bottom }
→ offset会消失!
🧩 超完整代码示例
📦 PromptAction封装类
// PromptActionClass.ets
import { BusinessError, ComponentContent, promptAction } from '@kit.ArkUI';
import { UIContext } from '@ohos.arkui.UIContext';
export class PromptActionClass {
static ctx: UIContext;
static contentNode: ComponentContent<Object>;
static options: promptAction.BaseDialogOptions;
// 三件套配置法✨
static setContext(context: UIContext) { this.ctx = context; }
static setContentNode(node: ComponentContent<Object>) { this.contentNode = node; }
static setOptions(options: promptAction.BaseDialogOptions) { this.options = options; }
// 一键开窗🚀
static openDialog() {
this.ctx.getPromptAction().openCustomDialog(this.contentNode, this.options)
.then(() => console.info('开窗成功! ✨'))
.catch((error: BusinessError) => this.handleError(error, 'Open'));
}
// 安全关窗🔒
static closeDialog() {
this.ctx.getPromptAction().closeCustomDialog(this.contentNode)
.then(() => console.info('关窗完毕~ 👋'))
.catch((error: BusinessError) => this.handleError(error, 'Close'));
}
// 动态更新🔄
static updateDialog(options: promptAction.BaseDialogOptions) {
this.ctx.getPromptAction().updateCustomDialog(this.contentNode, options)
.then(() => console.info('属性更新! 🎛️'))
.catch((error: BusinessError) => this.handleError(error, 'Update'));
}
// 错误处理统一包📦
private static handleError(error: BusinessError, type: string) {
console.error(`${type}弹窗失败❌|代码${error.code}|原因: ${error.message}`);
}
}
🖼️ 页面调用实战
// Index.ets
import { ComponentContent } from '@kit.ArkUI';
import { PromptActionClass } from './PromptActionClass';
class Params { text: string = ""; constructor(text: string) { this.text = text; } }
@Builder
function buildText(params: Params) {
Column() {
Text(params.text).fontSize(50).fontWeight(FontWeight.Bold).margin({ bottom: 36 })
Button('Close').onClick(() => PromptActionClass.closeDialog()) // 关键!调用静态方法
}.backgroundColor('#FFF0F0F0')
}
@Entry
@Component
struct Index {
@State message: string = "初始文案";
private ctx: UIContext = this.getUIContext();
private contentNode: ComponentContent<Object> =
new ComponentContent(this.ctx, wrapBuilder(buildText), new Params(this.message));
aboutToAppear(): void {
// 初始化三件套 🧾
PromptActionClass.setContext(this.ctx);
PromptActionClass.setContentNode(this.contentNode);
PromptActionClass.setOptions({ alignment: DialogAlignment.Top, offset: { dx: 0, dy: 50 } });
}
build() {
Row() {
Column() {
// 按钮1:开窗+改属性
Button("开窗并改属性 🎛️")
.margin({ top: 50 })
.onClick(() => {
PromptActionClass.openDialog();
setTimeout(() => PromptActionClass.updateDialog({
alignment: DialogAlignment.Bottom,
offset: { dx: 0, dy: -50 } // 1.5秒后下沉
}), 1500);
})
// 按钮2:开窗+改内容
Button("开窗并改文案 ✏️")
.margin({ top: 50 })
.onClick(() => {
PromptActionClass.openDialog();
setTimeout(() => this.contentNode.update(
new Params('更新后的酷炫文案!')), 1500); // 1.5秒后换字
})
}.width('100%')
}.height('100%')
}
}
💎 精华总结表
功能 | 实现方式 | 注意事项 |
---|---|---|
弹窗创建 | new ComponentContent() |
Params传参支持基础类型 |
开启弹窗 | openCustomDialog(contentNode) |
默认开启完全自定义样式 |
关闭弹窗 | closeCustomDialog(contentNode) |
必须调用dispose() 释放内存! |
更新内容 | contentNode.update(new Params()) |
避开@Reusable/@Link等装饰器 |
更新属性 | updateCustomDialog(options) |
未设置属性会重置为默认值! |
⚡ 闪电技巧包
- 内存卫士:关窗后必做
.dispose()
,否则内存泄漏警告!🚨 - 防重置术:更新属性时必须重传所有参数,不然会被系统默认值覆盖!
- 解耦大法:用
ComponentContent
替代Builder
,和UI界面离婚成功!💔 - 异步更新:在
setTimeout
中调更新方法,避免阻塞动效⏱️
更多推荐
所有评论(0)