最近有一个想法,做一个针对鸿蒙官方API的工具箱项目,介绍常用的控件,以及在项目中如何使用,今天介绍Harmony中如何实现弹窗功能。
警告弹窗
警告弹窗是一个App中非常常用的弹窗,例如:
- 删除一条记录,提示一下用户:您确定要删除吗?
- 在App首页,点击返回时,提示一下用户:您确定要退出App吗?
使用AlertDialog.show方法进行弹窗,这个方法支持传入以下三个类中的任意一个对象
- AlertDialogParamWithConfirm
- AlertDialogParamWithButtons
- AlertDialogParamWithOptions
以AlertDialogParamWithButtons对象进行说明,下面表格介绍常用属性:
参数名 | 参数类型 | 必填 | 参数描述 |
---|---|---|---|
title | ResourceStr | 否 | 弹窗标题 |
message | ResourceStr | 是 | 弹窗内容 |
autoCancel | boolean | 否 | 点击遮障层时,是否关闭弹窗。默认值:true |
primaryButton | {value: ResourceStr,fontColor?: ResourceColor,backgroundColor?: ResourceColor,action: () => void;} | 否 | 按钮的文本内容、文本色、按钮背景色和点击回调 |
secondaryButton | {value: ResourceStr,fontColor?: ResourceColor,backgroundColor?: ResourceColor,action: () => void;} | 否 | 按钮的文本内容、文本色、按钮背景色和点击回调 |
cancel | () => void | 否 | 点击遮障层关闭dialog时的回调 |
alignment | DialogAlignment | 否 | 弹窗在竖直方向上的对齐方式。默认值:DialogAlignment.Default |
接下来,我们用代码来实现一下:
AlertDialog.show({
title:"弹窗标题",
message:"这是弹窗内容",
autoCancel:true,//点击遮障层时,是否关闭弹窗。默认值:true
alignment: DialogAlignment.Center,//弹窗在竖直方向上的对齐方式。默认值:DialogAlignment.Default
primaryButton: {
value: "取消",
fontColor: '#181818',
action: () => {
AppUtil.showToast("点击了取消按钮");
}
},
secondaryButton: {
value: "确定",
fontColor: $r('app.color.mainColor'),
action: () => {
AppUtil.showToast("点击了确定按钮");
}
},
cornerRadius:12,//弹窗边框弧度
width:'80%', //弹窗宽度
cancel:()=>{
AppUtil.showToast("点击遮障层关闭dialog时的回调");
}
})
效果图:
参考官方链接:
自定义弹窗
自定义弹窗相比警告弹窗更为灵活,支持自定义弹窗的样式与内容。
自定义弹窗的参数:
参数名 | 参数类型 | 必填 | 参数描述 |
---|---|---|---|
builder | CustomDialog | 是 | 自定义弹窗内容构造器。 |
cancel | () => void | 否 | 点击遮障层退出时的回调。 |
autoCancel | boolean | 否 | 是否允许点击遮障层退出。默认值:true |
alignment | DialogAlignment | 否 | 弹窗在竖直方向上的对齐方式。默认值:DialogAlignment.Default |
offset | Offset | 否 | 弹窗相对alignment所在位置的偏移量。 |
customStyle | boolean | 否 | 弹窗容器样式是否自定义。默认值:false,弹窗容器的宽度根据栅格系统自适应,不跟随子节点;高度自适应子节点,最大为窗口高度的90%;圆角为24vp。 |
gridCount8+ | number | 否 | 弹窗宽度占栅格宽度的个数。默认为按照窗口大小自适应,异常值按默认值处理,最大栅格数为系统最大栅格数。 |
代码实现
我们使用自定义弹窗实现隐私政策弹窗,新建PrivacyPolicyDialogBackUp类,也就是内容构造器,使用@CustomDialog修饰,内部有一个属性controller: CustomDialogController,这些都是常规写法,然后在build中实现界面布局。
@CustomDialog
export default struct PrivacyPolicyDialogBackUp{
controller: CustomDialogController
cancel!: () => void
confirm!: () => void
build() {
Column() {
Text($r('app.string.simple_user_policy')).fontSize(18).fontColor($r('app.color.title_color')).margin({ top: 30, bottom: 19 })
Scroll(){
Text(){
Span($r('app.string.privacy_policy_start'))
Span($r('app.string.user_agreement_two')).fontColor($r('app.color.mainColor')).onClick(() => {
this.openWebUrl("/useragreement.html");
})
Span($r('app.string.and'))
Span($r('app.string.privacy_policy_two')).fontColor($r('app.color.mainColor')).onClick(() => {
this.openWebUrl("/privacypolicy.html");
})
Span($r('app.string.simple_privacy_policy'))
}.fontSize(16).fontColor($r('app.color.body_color')).margin({
left:25,
right:25
})
}.height(120)
Column(){
Button($r('app.string.disagree_privacy_policy')).onClick(() => {
this.controller.close();
this.cancel();
}).fontColor($r('app.color.other_color')).fontSize(15).backgroundColor(Color.Transparent)
Button($r('app.string.agree_privacy_policy')).onClick(() => {
this.controller.close();
this.confirm();
}).fontColor($r('app.color.white')).fontSize(17)
.linearGradient({
direction: GradientDirection.Right, colors:[[$r('app.color.start_main_color'),0.0],[$r('app.color.end_main_color'),1.0]]
}).width('80%').margin({
top:15,bottom:21
}).borderRadius(24)
}
}
}
openWebUrl(urlSuffix:string){
let url= AppConstant.URL+urlSuffix;
logger.info("url:"+url)
router.pushUrl({
url: Pages.WebViewPage,
params:{
data1: 'message',
url: url, // 传递的 URL 参数
}
}, router.RouterMode.Single)
}
}
在组件中创建CustomDialogController实例,指定builder属性,就是上面写的内容构造器
privacyPolicyDialog: CustomDialogController = new CustomDialogController({
builder: PrivacyPolicyDialog({
cancel:this.onCancel.bind(this),
confirm:this.onAgree.bind(this)
}),
alignment: DialogAlignment.Default, // 可设置dialog的对齐方式,设定显示在底部或中间等,默认为底部显示
cornerRadius:13,
autoCancel:false
})
显示弹窗
this.privacyPolicyDialog.open();
关闭弹窗
this.privacyPolicyDialog.close();
效果图:
参考官方链接:
加载中弹窗
加载中弹窗弹窗其实就是自定义弹窗实现,只是内容构造器不一样而已,给Image组件设置animation动画,无限循环图片
@CustomDialog
export default struct LoadingDialog {
controller: CustomDialogController
private loadingText: string|Resource = "加载中..."
@State angle:number = 10
aboutToAppear(){
setTimeout(()=>{
this.angle = 1440 // 设定一个大的旋转角度,确保动画执行
},100)
}
build() {
Column(){
Image($r('app.media.icon_loading_3'))
.width(70)
.height(70)
.rotate({angle:this.angle})
.animation({
duration: 5000,
curve: Curve.Linear,
delay: 0,
iterations: -1, // 设置-1表示动画无限循环
playMode: PlayMode.Normal
})
Text(this.loadingText).fontSize(14).fontColor(0xffffff).margin({top:10})
}.backgroundColor(0x88000000).borderRadius(10).padding({
left:20,right:20,top:10,bottom:10
})
}
}
效果图: