HarmonyOS7 弹窗全家桶:AlertDialog、CustomDialog、ActionSheet 一个都不落下

发布时间:2026/7/21 7:09:04
HarmonyOS7 弹窗全家桶:AlertDialog、CustomDialog、ActionSheet 一个都不落下 文章目录前言弹窗类型对比AlertDialog最简单的提示弹窗ActionSheet底部选项弹窗CustomDialog自定义弹窗的完整实现弹窗动画弹窗嵌套处理写在最后前言你敢信我之前项目里所有弹窗都用AlertDialog搞定产品经理说这个弹窗要加个输入框我直接傻了——AlertDialog 根本放不了自定义内容啊。后来才知道 CustomDialog 才是正解ActionSheet 又是另一种玩法。三种弹窗各有各的场用错了就是给自己挖坑。今天把这三种弹窗全讲一遍看完你就知道什么时候该用谁。弹窗类型对比先上对比表一目了然维度AlertDialogActionSheetCustomDialog用途简单提示/确认底部多选项完全自定义内容位置屏幕中央屏幕底部自由设定自定义内容不支持不支持完全自定义按钮数量1-3 个多个选项随你放调用方式全局方法全局方法Controller 控制复杂度最低低较高划重点简单的用 AlertDialog选操作用 ActionSheet啥都要自定义就用 CustomDialog。AlertDialog最简单的提示弹窗AlertDialog 适合你确定要删除吗这种场景一行代码搞定AlertDialog.show({title:提示,message:确定要退出登录吗,primaryButton:{value:取消,action:(){console.info(用户点了取消);}},secondaryButton:{value:确定,action:(){console.info(用户点了确定执行退出);}}});关键代码讲解primaryButton是主按钮通常放取消secondaryButton是次按钮通常放确认只需要单个按钮的话只写primaryButton就行action回调里处理点击逻辑弹窗点击按钮后自动关闭三个按钮的写法AlertDialog.show({title:文件已修改,message:是否保存更改,primaryButton:{value:不保存,action:(){}},secondaryButton:{value:取消,action:(){}},thirdButton:{value:保存,action:(){this.saveFile();}}});thirdButton是第三个按钮最多支持三个ActionSheet底部选项弹窗ActionSheet 从底部弹出适合选择图片来源这种多选项场景ActionSheet.show({title:选择图片来源,message:请选择照片获取方式,sheets:[{title:拍照,action:(){this.openCamera();}},{title:从相册选择,action:(){this.openGallery();}},{title:从文件选择,action:(){this.openFileManager();}}],confirm:{value:取消,action:(){}}});关键代码讲解sheets是选项数组每个选项有title和actionconfirm是底部的取消按钮点击关闭弹窗选项会按数组顺序从上到下排列通常把破坏性操作如删除放最后并标红实际项目里经常需要区分安全操作和危险操作ActionSheet.show({title:操作,sheets:[{title:编辑,action:(){}},{title:分享,action:(){}},{title:删除,action:(){this.deleteItem();}}],confirm:{value:取消,action:(){}}});删除这种危险操作UI 上通常用红色文字区分ActionSheet 本身不提供颜色配置这个得靠 CustomDialog 实现CustomDialog自定义弹窗的完整实现AlertDialog 和 ActionSheet 都只能放文字按钮CustomDialog 才是真正的大杀器——你想放啥放啥。完整代码逐行讲解CustomDialogstruct LoginDialog{controller?:CustomDialogController;Stateusername:string;Statepassword:string;onConfirm:(username:string,password:string)void(){};build(){Column({space:20}){Text(用户登录).fontSize(22).fontWeight(FontWeight.Bold)TextInput({placeholder:请输入用户名}).width(100%).onChange((value:string){this.usernamevalue;})TextInput({placeholder:请输入密码}).width(100%).type(InputType.Password).onChange((value:string){this.passwordvalue;})Row({space:16}){Button(取消).width(45%).backgroundColor(#E0E0E0).fontColor(#333).onClick((){this.controller?.close();})Button(登录).width(45%).onClick((){this.controller?.close();this.onConfirm(this.username,this.password);})}.width(100%).justifyContent(FlexAlign.SpaceBetween)}.padding(24).borderRadius(16).backgroundColor(Color.White)}}逐行讲解CustomDialog装饰器标记这是一个自定义弹窗组件controller?: CustomDialogController—— 控制器用来手动关闭弹窗必须声明为可选State username / password—— 弹窗内部的状态用于保存输入内容onConfirm—— 回调函数把输入结果传回调用方TextInputonChange—— 输入框的值实时同步到State变量this.controller?.close()—— 先关闭弹窗再执行回调避免弹窗卡住this.onConfirm(this.username, this.password)—— 把用户名密码传出去在页面中使用EntryComponentstruct LoginPage{privatedialogController:CustomDialogControllernewCustomDialogController({builder:LoginDialog({onConfirm:(username:string,password:string){this.doLogin(username,password);}}),alignment:DialogAlignment.Center,cornerRadius:16,width:80%});privatedoLogin(username:string,password:string):void{console.info(登录${username},${password});}build(){Column(){Button(登录).onClick((){this.dialogController.open();})}.width(100%).height(100%).justifyContent(FlexAlign.Center)}}CustomDialogController在Component内定义builder参数指向你的弹窗组件回调函数在builder里传入实现弹窗 → 页面的数据回传alignment控制弹窗位置DialogAlignment.Center是居中还有Bottom、Top等弹窗动画CustomDialog 支持自定义出现和消失动画privatedialogController:CustomDialogControllernewCustomDialogController({builder:LoginDialog({onConfirm:(){}}),transitionAction:(transition:TransitionProxy){if(transition.transitionEffect){transition.performTransition();}},showTransition:TransitionEffect.OPACITY.combine(TransitionEffect.SLIDE({direction:SlideDirection.DOWN})),hideTransition:TransitionEffect.OPACITY.combine(TransitionEffect.SLIDE({direction:SlideDirection.UP}))});showTransition控制弹窗出现的动画效果hideTransition控制弹窗消失的动画效果TransitionEffect.OPACITY是透明度渐变SLIDE是滑动方向combine可以组合多个动画效果弹窗嵌套处理真做项目的时候弹窗里弹弹窗是常事。但有个坑CustomDialog 里不能再直接 open 另一个 CustomDialog。解决方案用setTimeout延迟打开让第一个弹窗完全关闭后再开第二个Button(删除).onClick((){this.controller?.close();setTimeout((){this.confirmDialogController.open();},300);})300ms 的延迟是经验值足够让前一个弹窗的关闭动画完成如果弹窗有更长的关闭动画可以适当加大延迟真香警告如果嵌套层级太深3 层以上建议重构交互流程用页面导航代替弹窗嵌套。写在最后弹窗这东西选对类型就成功了一半。AlertDialog 能搞定的别用 CustomDialog代码量差了十倍不止。但反过来需要自定义内容的场景硬上 AlertDialog 也很痛苦——放不了输入框、改不了布局、控制不了样式。我的经验是项目一开始就封装一套弹窗工具类三种类型各一个快捷方法用到的时候一行调用。别在每个页面里重复写弹窗逻辑维护起来想死。