HarmonyOS鸿蒙Next中openCustomDialog mask蒙层如何添加blur效果
HarmonyOS鸿蒙Next中openCustomDialog mask蒙层如何添加blur效果 https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-uicontext-custom-dialog
文档里没找到blur相关的api
目前只能外面包一层容器实现blur效果
但是这样有个问题我想实现点击遮罩自动关闭
autoCancel: true,
这个配置项就无效了
因为弹窗占了 100% 100%
然后又尝试给外层容器添加关闭事件
.onClick(() => {
this.vm.closeDialog()
})
这样就会导致冒泡问题点击 dialog 本身也会触发关闭
这里不知道如何处理了
请问后续有打算内置蒙层模糊的配置项吗
更多关于HarmonyOS鸿蒙Next中openCustomDialog mask蒙层如何添加blur效果的实战教程也可以访问 https://www.itying.com/category-93-b0.html
开发者您好,为了支持该问题走需求评估流程,需要您补充反馈使用场景和需求不满足可能带来的影响,例如:
原始场景:什么样的业务场景?什么样的交互流程?哪一个过程遇到了问题?
影响:什么时间用到?是否高频?有无三方库可以做到?若提供该能力,是否会造成大工作量返工?
更多关于HarmonyOS鸿蒙Next中openCustomDialog mask蒙层如何添加blur效果的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
你的问题加一个空的点击事件就好
我自己写了一下你的功能,你可以看看
import { BusinessError } from '@kit.BasicServicesKit';
import { ComponentContent, display, promptAction, UIContext } from '@kit.ArkUI';
export class PromptActionClass {
static ctx: UIContext;
static contentNode: ComponentContent<Object>;
static options: promptAction.BaseDialogOptions;
static setContext(context: UIContext) {
PromptActionClass.ctx = context;
}
static setContentNode(node: ComponentContent<Object>) {
PromptActionClass.contentNode = node;
}
static setOptions(options: promptAction.BaseDialogOptions) {
PromptActionClass.options = options;
}
static openDialog() {
if (PromptActionClass.contentNode !== null) {
PromptActionClass.ctx.getPromptAction().openCustomDialog(PromptActionClass.contentNode, PromptActionClass.options)
.then(() => {
console.info('OpenCustomDialog complete.');
})
.catch((error: BusinessError) => {
let message = (error as BusinessError).message;
let code = (error as BusinessError).code;
console.error(`OpenCustomDialog args error code is ${code}, message is ${message}`);
})
}
}
static closeDialog() {
if (PromptActionClass.contentNode !== null) {
PromptActionClass.ctx.getPromptAction().closeCustomDialog(PromptActionClass.contentNode)
.then(() => {
console.info('CloseCustomDialog complete.');
})
.catch((error: BusinessError) => {
let message = (error as BusinessError).message;
let code = (error as BusinessError).code;
console.error(`CloseCustomDialog args error code is ${code}, message is ${message}`);
})
}
}
static updateDialog(options: promptAction.BaseDialogOptions) {
if (PromptActionClass.contentNode !== null) {
PromptActionClass.ctx.getPromptAction().updateCustomDialog(PromptActionClass.contentNode, options)
.then(() => {
console.info('UpdateCustomDialog complete.');
})
.catch((error: BusinessError) => {
let message = (error as BusinessError).message;
let code = (error as BusinessError).code;
console.error(`UpdateCustomDialog args error code is ${code}, message is ${message}`);
})
}
}
}
class Params {
text: string = "";
constructor(text: string) {
this.text = text;
}
}
@Builder
function buildText(params: Params) {
//朦层
Column() {
//实际弹窗内容
Column(){
Text(params.text)
.fontSize(50)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 36 })
}
.backgroundColor('#fff')
//todo 加入空的点击事件就不会关闭了
.onClick(()=>{
})
}
.width('100%')
.height('100%')
//获取顶部安全区
// let topHeight = win.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM).topRect.height;
// let bottomHeight = win.getWindowAvoidArea(window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR).bottomRect.height;
// this.topPadding = px2vp(topHeight)
// this.bottomPadding = px2vp(bottomHeight)
//.margin({ top: -topHeight })
.margin({ top: -40 })//todo 此处40需要替换为顶部安全区高度topHeight,因为朦层会侵入安全区,所以做假朦层也要侵入安全区
.padding({ top: 40 })
//此处设置沉浸式失效,所以得用 .margin({ top: -topHeight }) 来做沉浸式
//.expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])
.backgroundColor('#ff433535')
.backdropBlur(20)
.onClick(() => {
PromptActionClass.closeDialog();
})
}
@Entry
@Component
struct Index {
@State message: string = "hello";
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 } ,
maskColor: Color.Red
});
}
build() {
Row() {
Column() {
Button("open dialog and update options")
.margin({ top: 50 })
.onClick(() => {
PromptActionClass.openDialog();
})
}
.width('100%')
.height('100%')
}
.height('100%')
}
}
@Entry
@Component
struct Index {
dialogController: CustomDialogController = new CustomDialogController({
builder: CustomBlurDialog(),
})
build() {
Column() {
Button('click me')
.onClick(() => {
this.dialogController.open();
})
}.width('100%').margin({ top: 5 })
}
}
@CustomDialog
struct CustomBlurDialog {
controller: CustomDialogController
@State isContentTouched: boolean = false
build() {
Stack() {
// 模糊蒙层
Column()
.width('100%')
.height('100%')
.backgroundColor(Color.White)
.backdropBlur(10)
.onClick(() => this.controller?.close())
// 弹窗内容
Column() {
Text('自定义弹窗')
.fontSize(20)
.margin(20)
Button('关闭')
.onClick(() => this.controller.close())
}
.backgroundColor(Color.White)
.borderRadius(16)
.width('80%')
.hitTestBehavior(HitTestMode.Block)
}
}
}
模糊效果选择:优先使用backdropBlur而非外部容器包裹,确保性能最优
事件控制层级:通过hitTestBehavior精准控制事件响应范围
布局结构优化:通过Stack分层实现蒙层与内容的视觉分离
autoCancel替代方案:自行实现点击判断逻辑更灵活可控
autoCancel失效问题:
- 通过
.onClick
手动绑定蒙层点击事件 - 点击冒泡问题:
- 给内容容器添加阻断属性
在HarmonyOS Next中,为openCustomDialog的mask蒙层添加blur效果,需使用ModalTransitionStyle配置。在自定义弹窗组件内,通过设置modalTransitionStyle属性为ModalTransitionStyle.BLUR实现蒙层模糊效果。
具体代码示例:
openCustomDialog(this, {
modalTransitionStyle: ModalTransitionStyle.BLUR,
builder: CustomDialogComponent
})
该属性直接作用于弹窗蒙层,无需额外样式配置。模糊效果由系统自动处理,适配不同设备。
目前HarmonyOS Next的openCustomDialog确实没有内置mask蒙层的blur模糊效果API。你遇到的问题是合理的,因为当自定义蒙层覆盖整个屏幕时,autoCancel配置会失效。
针对点击冒泡问题,可以通过事件判断来解决:
.onClick((event: ClickEvent) => {
// 判断点击的是蒙层而不是dialog内容区域
if (event.target === yourMaskComponent) {
this.vm.closeDialog()
}
})
或者使用HitTestBehavior控制点击穿透:
.mask({
type: MaskType.Solid,
color: 0x33000000
})
.hitTestBehavior(HitTestMode.Block)
关于内置模糊效果的需求,建议通过官方反馈渠道提交功能建议。目前推荐的做法还是使用自定义蒙层方案,通过精确控制点击事件处理来解决关闭问题。