前言:
鸿蒙官方提供了自定义customdialog,调用代码很臃肿,必须在当前页面创建customDialogController,否则无法正常弹窗dialog
解决方案:目前就定义了两种类型的dialog
具体代码如下:
1. 用于代理dialog的打开和关闭
export interface MyCustomDialogController {
open: () => void
close: () => void
}
2. 作为全局弹窗组件封装 内容完全由外部dialogContent定义
@CustomDialog
export default struct MyCustomDialog {
controller: CustomDialogController
@BuilderParam dialogContent: () => void
build() {
this.dialogContent()
}
}
3.1. 具体实现,这里是ConfirmPop(对话框弹窗)
import MyCustomDialog from './core/MyCustomDialog';
import { MyCustomDialogController } from './core/MyCustomDialogController';
/**
* @author: hwk
* @description: 确认取消对话框弹窗
* @date: 2024/3/7 10:33
*/
@Component
export default struct ConfirmPop {
controller: MyCustomDialogController = null;
alignment: DialogAlignment = DialogAlignment.Center; //弹窗位置
offsetX: number = 0; //上下 偏移量 负数则往上
offsetY: number = 0; //上下 偏移量 负数则往上
autoCancel: boolean = false; //点击遮罩层是否关闭弹窗
//api9不支持 maskColor: ResourceColor = "rgba(0,0,0,0.1)";
customStyle: true;
title: Resource;
content: Resource;
leftText: Resource = $r('app.string.quxiao');
rightText: Resource = $r('app.string.queding');
isHideRight: boolean = false; //是否隐藏右边按钮
leftClick: () => void
rightClick: () => void
//下面两个是私有的
@State leftDown: boolean = false; //左边按钮是否按下
@State rightDown: boolean = false; //右边按钮是否按下
build() {
}
@Builder buildContent() {
Column() {
Text(this.title)
.fontSize(15)
.fontColor($r('app.color.black3'))
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
Text(this.content)
.fontSize(13)
.fontColor($r('app.color.black6'))
.maxLines(3)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.margin({ top: 13, bottom: 30 })
Row() {
Text(this.leftText)
.height('100%')
.width(86)
.textAlign(TextAlign.Center)
.fontSize(13)
.backgroundColor(this.leftDown ? $r('app.color.theme') : $r('app.color.white'))
.fontColor(this.leftDown ? $r('app.color.white') : $r('app.color.theme'))
.border({ width: 1, color: $r('app.color.theme'), radius: 5, style: BorderStyle.Solid })
.onTouch((event: TouchEvent) => {
this.leftDown = (event.type != TouchType.Up);
})
.onClick(() => {
this.controller.close()
if (this.leftClick)
this.leftClick()
})
Blank()
.visibility(this.isHideRight ? Visibility.None : Visibility.Visible)
.width(20)
.height('100%')
Text(this.rightText)
.visibility(this.isHideRight ? Visibility.None : Visibility.Visible)
.height('100%')
.width(86)
.textAlign(TextAlign.Center)
.fontSize(13)
.backgroundColor(this.rightDown ? $r('app.color.theme') : $r('app.color.white'))
.fontColor(this.rightDown ? $r('app.color.white') : $r('app.color.theme'))
.border({ width: 1, color: $r('app.color.theme'), radius: 5, style: BorderStyle.Solid })
.onTouch((event: TouchEvent) => {
this.rightDown = (event.type != TouchType.Up);
})
.onClick(() => {
this.controller.close()
if (this.rightClick)
this.rightClick()
})
}
.width('100%')
.height(34)
.padding({ left: 12, right: 12 })
.justifyContent(FlexAlign.Center)
}
.width(250)
.backgroundColor($r('app.color.white'))
.borderRadius(5)
.padding({ left: 17, right: 17, top: 12, bottom: 22 })
}
aboutToAppear() {
//修正,这里要在这里初始化,否则 this.clickMaskClose 不能响应外部变更
let dialogController = new CustomDialogController({
builder: MyCustomDialog({
dialogContent: () => {
this.buildContent();
}
}),
alignment: this.alignment,
offset: { dx: 0, dy: this.offsetY },
// maskColor: this.maskColor,
autoCancel: this.autoCancel,
//完全依靠外部样式控制,否则会有宽度限制和默认圆角, 这里需要的就是要自己控制样式
customStyle: true
});
if (this.controller) {
this.controller.open = () => {
dialogController.open();
}
this.controller.close = () => {
dialogController.close();
}
}
}
}
3.2. 具体实现,这里是LoadingPop(加载中弹窗)
import MyCustomDialog from './core/MyCustomDialog';
import { MyCustomDialogController } from './core/MyCustomDialogController';
/**
* @author: hwk
* @description: 加载动画loading
* @date: 2024/3/7 14:12
*/
@Component
export default struct LoadingPop {
controller: MyCustomDialogController = null;
alignment: DialogAlignment = DialogAlignment.Center; //弹窗位置
offsetX: number = 0; //上下 偏移量 负数则往上
offsetY: number = 0; //上下 偏移量 负数则往上
autoCancel: boolean = false; //点击遮罩层是否关闭弹窗
//api9不支持 maskColor: ResourceColor = "rgba(0,0,0,0.1)";
customStyle: true;
@State angle: number = 0
build() {
}
@Builder buildContent() {
Column() {
ImageAnimator()
Image($r('app.media.loading'))
.width(50)
.margin({ top: 16 })
.rotate({ angle: this.angle })
.animation({
duration: 1500,
curve: Curve.Linear,
iterations: -1, // 设置-1表示动画无限循环
playMode: PlayMode.Normal
})
Text('加载中...')
.margin({ top: 16 })
.fontColor($r('app.color.white'))
.fontSize(12)
}
.width(111)
.height(111)
.borderRadius(5)
.backgroundColor($r('app.color.transparent50'))
}
aboutToAppear() {
//修正,这里要在这里初始化,否则 this.clickMaskClose 不能响应外部变更
let dialogController = new CustomDialogController({
builder: MyCustomDialog({
dialogContent: () => {
this.buildContent();
}
}),
alignment: this.alignment,
offset: { dx: 0, dy: this.offsetY },
autoCancel: this.autoCancel,
//完全依靠外部样式控制,否则会有宽度限制和默认圆角, 这里需要的就是要自己控制样式
customStyle: true
});
if (this.controller) {
this.controller.open = () => {
dialogController.open();
this.timeoutId = setTimeout(() => {
this.angle = 360;
}, 10)
}
this.controller.close = () => {
clearTimeout(this.timeoutId);
dialogController.close();
}
}
}
timeoutId: number;
}
4. 调用