《级联年度选择》二、CustomDialog使用指南
HarmonyOS ArkTS 自定义弹窗CustomDialog使用指南本文系统讲解 HarmonyOS 中自定义弹窗CustomDialog的完整使用方法从基本概念到实战示例帮助你掌握 CustomDialogController 的核心 API 和弹窗开发全流程。效果一、CustomDialog 概述1.1 什么是 CustomDialogCustomDialog是 ArkUI 提供的自定义弹窗机制允许开发者通过CustomDialog装饰器定义弹窗内容并通过CustomDialogController控制器管理弹窗的显示与隐藏。与系统默认弹窗如AlertDialog相比CustomDialog具有更高的灵活性可以自由定制弹窗的布局、样式和交互逻辑适用于广告展示、确认对话框、信息录入、筛选面板等场景。1.2 核心组成组成部分说明CustomDialog装饰器标记一个 struct 为自定义弹窗组件CustomDialogController控制器类负责弹窗的创建、打开和关闭open()方法显示弹窗close()方法关闭弹窗二、CustomDialogController 详解2.1 基本用法CustomDialogController必须在Component的 struct 内部声明为成员变量并赋值才有效dialogController:CustomDialogControllernewCustomDialogController({builder:MyCustomDialog(),// 弹窗内容构建器autoCancel:true,// 点击遮罩层是否关闭alignment:DialogAlignment.Center,// 弹窗对齐方式customStyle:false,// 是否使用自定义样式})2.2 配置参数一览参数类型默认值说明builderCustomDialog必选自定义弹窗的内容构建器cancel() void-点击遮罩层、返回键、ESC 键退出时的回调autoCancelbooleantrue是否允许点击遮罩层关闭弹窗alignmentDialogAlignmentDefault弹窗对齐方式Center/Top/BottomoffsetOffset-弹窗相对对齐位置的偏移量customStylebooleanfalsetrue时使用自定义样式去除系统默认背景和圆角cornerRadiusnumber | Resource-弹窗圆角半径widthstring | number-弹窗宽度heightstring | number-弹窗高度borderWidthnumber-边框宽度borderColorColor-边框颜色onWillDismiss(action) void-弹窗即将关闭时的拦截回调API 122.3 控制器方法方法说明open()显示弹窗。可多次调用但如果弹窗已显示则不会重复弹出close()关闭弹窗。如果已关闭则不生效三、定义自定义弹窗组件3.1 基本结构使用CustomDialog和Component同时装饰 struct并声明controller属性ComponentCustomDialogstruct MyCustomDialog{controller:CustomDialogController|nullnullbuild(){Column({space:16}){Text(弹窗标题).fontSize(18).fontWeight(FontWeight.Bold)Text(这里是弹窗的内容区域).fontSize(14)Button(关闭).onClick((){this.controller?.close()})}.padding(24)}}重要controller属性是必须的。如果不声明编译器会报错CustomDialog component should have a property of the CustomDialogController type.3.2 数据传递弹窗组件可以通过Link、Prop等装饰器与父组件进行数据同步装饰器数据方向说明Link双向绑定弹窗内修改数据会同步到父组件Prop单向传递父组件数据传入弹窗弹窗内修改不影响父组件Consume/Provide跨层级适用于多层嵌套的数据共享四、完整实战示例用户反馈弹窗4.1 效果说明主页面有一个提交反馈按钮点击按钮弹出自定义弹窗包含评分选择、文本输入和提交/取消按钮提交后弹窗关闭主页面显示反馈结果支持点击遮罩层关闭弹窗从底部弹出带有圆角效果4.2 弹窗组件代码// FeedbackDialog.etsComponentCustomDialogexportstruct FeedbackDialog{controller:CustomDialogController|nullnullStaterating:number5StatefeedbackText:stringonSubmit?:(rating:number,text:string)voidonCancel?:()voidbuild(){Column({space:16}){// 标题行Row(){Text(提交反馈).fontSize(18).fontWeight(FontWeight.Bold).layoutWeight(1)Text(✕).fontSize(20).onClick((){this.controller?.close()if(this.onCancel){this.onCancel()}})}.width(100%)// 评分区域Row({space:8}){ForEach([1,2,3,4,5],(star:number){Text(starthis.rating?★:☆).fontSize(28).fontColor(starthis.rating?#FFC107:#CCCCCC).onClick((){this.ratingstar})})}.width(100%).justifyContent(FlexAlign.Center)// 输入区域TextArea({placeholder:请输入您的反馈意见选填,text:this.feedbackText}).height(100).fontSize(14).backgroundColor(#F5F5F5).borderRadius(8).onChange((value:string){this.feedbackTextvalue})// 按钮区域Row({space:12}){Button(取消).fontSize(14).backgroundColor(#F0F0F0).fontColor(#666666).layoutWeight(1).onClick((){this.controller?.close()if(this.onCancel){this.onCancel()}})Button(提交).fontSize(14).backgroundColor(#4FC3F7).fontColor(Color.White).layoutWeight(1).onClick((){this.controller?.close()if(this.onSubmit){this.onSubmit(this.rating,this.feedbackText)}})}.width(100%)}.padding(24).width(100%)}}4.3 主页面代码// FeedbackPage.etsimport{FeedbackDialog}from../components/FeedbackDialogEntryComponentstruct FeedbackPage{StatefeedbackResult:stringStatehasSubmitted:booleanfalsedialogController:CustomDialogControllernewCustomDialogController({builder:FeedbackDialog({onSubmit:(rating:number,text:string){this.feedbackResult评分${rating}星 | 反馈${text||无}this.hasSubmittedtrue},onCancel:(){this.feedbackResult已取消提交this.hasSubmittedtrue}}),autoCancel:true,alignment:DialogAlignment.Bottom,customStyle:true,cornerRadius:16,width:100%,offset:{dx:0,dy:0}})build(){Column({space:20}){Text(反馈中心).fontSize(22).fontWeight(FontWeight.Bold).margin({top:24})Button(提交反馈,{type:ButtonType.Capsule}).fontSize(16).backgroundColor(#4FC3F7).fontColor(Color.White).width(200).onClick((){this.dialogController.open()})if(this.hasSubmitted){Column({space:8}){Text(最近提交结果).fontSize(14).fontColor(#888888)Text(this.feedbackResult).fontSize(15).padding(12).backgroundColor(#F5F5F5).borderRadius(8).width(100%)}.padding(16).margin({top:8})}Blank()}.width(100%).height(100%).padding({left:16,right:16}).backgroundColor(#FAFAFA)}}4.4 关键代码解析1弹窗控制器配置dialogController:CustomDialogControllernewCustomDialogController({builder:FeedbackDialog({...}),alignment:DialogAlignment.Bottom,// 从底部弹出customStyle:true,// 使用自定义样式cornerRadius:16,// 圆角 16vp})customStyle: true去除了系统默认的弹窗背景和圆角让弹窗完全按照自定义布局显示。2弹窗内回调机制通过函数属性onSubmit和onCancel实现弹窗与父组件的通信。弹窗关闭前调用回调函数将数据传递给父组件。3弹窗关闭this.controller?.close()使用可选链调用close()方法确保 controller 存在时才执行关闭操作。五、onWillDismiss 拦截关闭API 12onWillDismiss允许在弹窗即将关闭时进行拦截判断根据关闭原因决定是否真正关闭dialogController:CustomDialogControllernewCustomDialogController({builder:MyDialog(),onWillDismiss:(dismissAction:DismissDialogAction){// 根据关闭原因判断if(dismissAction.reasonDismissReason.PRESS_BACK){dismissAction.dismiss()// 允许返回键关闭}if(dismissAction.reasonDismissReason.TOUCH_OUTSIDE){// 不关闭继续显示弹窗}if(dismissAction.reasonDismissReason.CLOSE_BUTTON){dismissAction.dismiss()}}})DismissReason枚举值值说明PRESS_BACK用户按返回键TOUCH_OUTSIDE点击遮罩层CLOSE_BUTTON调用 close 方法六、最佳实践与注意事项6.1 注意事项注意点说明弹窗不支持动态刷新参数CustomDialogController的配置参数在初始化后不可更改页面跳转不自动关闭路由跳转时需手动调用close()关闭弹窗controller 销毁置空组件销毁时建议将controller置为null避免弹窗嵌套不要在弹窗内再弹出 SubWindow 模式的弹窗6.2 使用建议优先使用 CustomDialog比AlertDialog更灵活可完全定制样式和交互。数据同步用Link需要弹窗与父组件双向同步数据时使用Link装饰器。回调函数传结果弹窗内操作结果通过回调函数传递给父组件保持数据流向清晰。使用customStyle需要自定义弹窗背景、圆角时设置customStyle: true。合理利用alignment底部弹窗用Bottom确认弹窗用Center适配不同场景。七、参考链接CustomDialog 官方 API 文档CustomDialogController 参数说明弹窗概述
