写点什么

HarmonyOSNext 一看就懂!ArkUI 弹出框全方位攻略:从自定义到固定,玩转弹窗不迷糊!

作者:Turing_010
  • 2025-06-11
    广东
  • 本文字数:4682 字

    阅读完需:约 15 分钟

HarmonyOSNext一看就懂!ArkUI弹出框全方位攻略:从自定义到固定,玩转弹窗不迷糊!

##Harmony OS Next ##Ark Ts ##教育

本文适用于教育科普行业进行学习,有错误之处请指出我会修改。

嗨,小伙伴们!👋 搞开发的时候,“弹出框”(弹窗)这玩意儿绝对是我们经常打交道的老朋友了。它就像是你工作时突然跳出来的一个小房间,你必须先把这小房间里的任务搞定了(点个按钮啊、选个东西啊),才能关掉它,继续处理后面屏幕的事儿。

ArkUI 呢,超级贴心地给我们准备好了一整套弹窗解决方案,简单来说,分成两个门派

  1. 🎨 自定义弹出框:想搞点独特设计?没问题!你来搭舞台、填内容!

  2. 🔧 固定样式弹出框:就想快速搞定个按钮或者选择器?拿来即用超省心!

下面咱们就掰开揉碎,好好聊聊这些弹窗怎么用、用在哪!


🧩 一、弹窗家族大起底:你想用哪种?

🔮 门派一:自定义弹出框 (DIY 达人最爱!)

想象一下,弹窗就是个空盒子。里面的布局?组件?全靠你自由发挥!ArkUI 提供两种实现方式:

  1. CustomDialog (基础版自定义)

    用在哪? 当你需要完全掌控弹窗里面长啥样的时候!想塞按钮、图片、输入框、列表?统统你说了算!

    怎么用? 基本就是创建个自定义组件,然后把这个组件当作 CustomDialog 的内容塞进去。

  2. openCustomDialog (灵活版自定义)

    用在哪? 这个厉害了!当你需要在弹窗弹出之后,还能动态改它的标题、按钮、样式这些属性的时候,选它就对了!

    怎么用? 也是塞个自定义组件进去,但它给你留了接口 (像是 controller),方便你玩动态修改。

🛠 门派二:固定样式弹出框 (快速开箱!)

ArkUI 已经设计好的现成弹窗模版,你只要填上文字内容,设定下按钮操作就齐活,布局不用操心!省心又方便!


  1. AlertDialog (警告弹窗 - 重要通知!)


    用在哪? 用户必须立刻知道或确认的事情!比如,要删除一个重要文件啦?进行个敏感操作啦?必须让用户“看清且点确认”的场景。

    感觉像啥? ⚠️ “亲,真的要删除吗?删了可就回不来啦!”


  2. ActionSheet (列表选择弹窗 - 菜单式选项)


    用在哪? 需要用户从一个选项列表(比如操作菜单:删除、重命名、分享)里选一个的时候。

    感觉像啥? 📋 “想对这张图干啥?保存?分享?还是删掉?”


  3. PickerDialog (选择器弹窗 - 滑动选值)


    用在哪? 让用户滑动选择日期、时间、文本(比如省市县三级选择)的时候!

    感觉像啥? 📅 “选个生日?” ⏰ “几点见面?” 📍 “选个城市吧!”


  4. showDialog (通用对话框 - 带结果回调)


    用在哪? 当你需要一个简单的弹窗(标题 + 信息 + 按钮),并且想在用户点击按钮后,知道 TA 点了哪个、执行后续操作的时候。

    特点: 它提供 Promise 或回调函数异步返回用户点了哪个按钮。


  5. showActionMenu (操作菜单 - 类似 ActionSheet,带回调)


    用在哪? 作用和 ActionSheet 很像(都是列表菜单),关键区别在于:它在用户做出选择后,会异步返回用户点了哪个选项的索引号

    特点: 也提供 Promise 或回调函数异步返回用户点了哪个菜单项。

🧭 选择困难症?快查表!


⚠️ 二、重要!使用前的必读事项 (规矩得懂!)

弹窗虽好,不能乱用!有几个关键约束一定要记住:

  1. 📌 UI 上下文是命根子!

    UIContext.getPromptAction().showDialogshowActionMenuopenCustomDialog 这仨哥们,以及 PickerDialog 家族里的大部分成员(DatePickerDialog, TimePickerDialog, TextPickerDialog),包括 showAlertDialogshowActionSheet,都 严重依赖 UI 执行上下文

    翻译成人话: 你不能在 UI 上下文不明确的地方(比如某些异步回调深处、后台任务里)直接使用它们!会报错!


    解决方法:

    优先获取

     UIContext

    在组件内部,用 this.getUIContext()

    别的地方,试试 getUIContext()

    唯一例外(目前): CalendarPickerDialog 不能 通过 UIContext 调用 show 方法 (直接用 CalendarPickerDialog.show())。

  2. 📍 上下文获取路线图:


    对于 showActionMenushowDialog:


     // 在你的组件里(比如在 onClick 方法里):  let uiContext = this.getUIContext(); // 拿到 UI 上下文  let promptAction: PromptAction = uiContext.getPromptAction(); // 获取 PromptAction 对象  promptAction.showDialog({...}); // 或 promptAction.showActionMenu({...})


    对于 AlertDialog, ActionSheet, PickerDialog (除 CalendarPickerDialog):


     // 在你的组件里:  let uiContext = this.getUIContext(); // 拿到 UI 上下文  uiContext.showAlertDialog({...}); // 或 uiContext.showActionSheet({...}), uiContext.showDatePickerDialog({...}) 等

  3. 🔐 模态还是非模态?可选!

    showActionMenushowDialogActionSheetAlertDialog 这几个,可以设置参数 isModal: false。设置后,弹窗就变成“非模态”了!啥意思?就是弹窗跳出来,你不用立刻理它,可以先去点弹窗外面的内容!是不是更灵活了?


🚀 三、实战代码沙场!动手敲起来!

光说不练假把式,上硬菜!看代码最直观!(记得根据前面说的规则获取 UIContext 哦,这里省点篇幅)

🍔 案例一:操作菜单 (showActionMenu)

 import { PromptAction } from '@kit.ArkUI'; ​ let uiContext = this.getUIContext(); // 步骤1:搞到上下文 let promptAction: PromptAction = uiContext.getPromptAction(); // 步骤2:拿到PromptAction小助手 ​ // 开整!弄个菜单出来~ try {   promptAction.showActionMenu({     title: '爱吃啥水果? 🍉', // 菜单标题     buttons: [       { text: '苹果 🍎', color: '#FF3B30' }, // 选项1       { text: '香蕉 🍌', color: '#FF9500' }, // 选项2       { text: '西瓜 🍉', color: '#34C759' }, // 选项3     ]   })     .then(data => {       console.info('用户点了第' + (data.index + 1) + '个选项:' + data.text); // data.index 是按钮索引(0开始)     })     .catch((err: Error) => {       console.error('出问题啦!' + err); // 出错就逮住它!     }) } catch (error) {   console.error('初始化就出错!' + error); }
复制代码

💬 案例二:通用对话框 (showDialog)

 import { PromptAction } from '@kit.ArkUI'; ​ let uiContext = this.getUIContext(); let promptAction: PromptAction = uiContext.getPromptAction(); ​ try {   promptAction.showDialog({     title: '真的要退出吗?😢', // 对话框标题     message: '辛苦编辑的内容还没保存哦!', // 提示信息     buttons: [       { text: '我再想想', color: '#8E8E93' }, // 按钮1       { text: '狠心退出', color: '#007AFF' }   // 按钮2(通常设为高亮)     ]   }, (err, data) => { // 使用回调函数处理结果     if (err) {       console.error('弹窗出问题!' + err);       return;     }     console.info('用户点了:' + data.index); // 0: "我再想想", 1: "狠心退出"     if (data.index === 1) {       // 执行退出逻辑...     }   }); } catch (error) {   console.error('初始化就出错!' + error); }
复制代码

📆 案例三:日期选择器弹窗 (DatePickerDialog)

 @Entry @Component struct MyPage {   @State selectedDate: Date = new Date('2024-06-12'); // 当前选中日期 ​   build() {     Column() {       Button('选个好日子 📅')         .margin(20)         .onClick(() => {           let uiContext = this.getUIContext(); // 本组件内部获取UIContext           uiContext.showDatePickerDialog({             start: new Date("1990-01-01"), // 最早可选日期             end: new Date("2030-12-31"),   // 最晚可选日期             selected: this.selectedDate,   // 初始选中日期             lunarSwitch: true,             // 显示农历切换开关             showTime: true,                // 显示时间选择(时/分)             onDateAccept: (pickedDate: Date) => { // 用户点确认               this.selectedDate = pickedDate; // 更新选中日期               console.info('你选的日子是:' + pickedDate.toLocaleString());             }           })         })     }   } }
复制代码

🎨 案例四:花里胡哨列表弹窗 (ActionSheet + 样式)

 @Entry @Component struct StylishSheet {   build() {     Column() {       Button('来个炫酷菜单 ✨')         .margin(30)         .onClick(() => {           let uiContext = this.getUIContext();           uiContext.showActionSheet({             title: '炫酷功能菜单 🚀',             message: '挑一个试试看!',             autoCancel: true, // 点外面空白处自动关闭             width: '90%',    // 宽度占屏幕90%             cornerRadius: 24, // 圆角大一点             borderWidth: 2,             borderStyle: BorderStyle.Solid,             borderColor: Color.Magenta, // 骚气紫边框             backgroundColor: Color.Black, // 酷黑背景             transition: TransitionEffect.asymmetric(               // 弹出动画:淡入+放大 (3秒,有点慢为了看清效果,实际别用这么长)               TransitionEffect.OPACITY.animation({ duration: 3000, curve: Curve.Ease })                 .combine(TransitionEffect.scale({ x: 0.8, y: 0.8 }).animation({ duration: 3000, curve: Curve.Ease })),               // 关闭动画:淡出+缩小 (快一点,0.3秒)               TransitionEffect.OPACITY.animation({ duration: 300, curve: Curve.EaseIn })                 .combine(TransitionEffect.scale({ x: 0.8, y: 0.8 }).animation({ duration: 300, curve: Curve.EaseIn }))             ),             confirm: { // 底部那个大大的确认按钮(实际这里可能是“取消”)               value: '收工!👋',               fontColor: Color.White,               backgroundColor: Color.Blue,               action: () => console.info('用户点了确认(取消)按钮')             },             sheets: [               { title: '开灯💡', action: () => console.log('灯亮了!') },               { title: '放音乐🎵', action: () => console.log('Music!') },               { title: '旋转跳跃💃', action: () => console.log('转起来!') }             ]           });         })     }   } }
复制代码

🔑 四、核心要点再唠叨!(必看总结)

🚨 重中之重!UI 上下文! 再强调一遍:大部分弹窗 (showDialog, showActionMenu, PickerDialog, AlertDialog, ActionSheet) 都需要在有效的 UI 上下文中调用!用 getUIContext()this.getUIContext() 准没错!只有 CalendarPickerDialog 目前是个特例,直接调 show() 就行。

🪄 小技巧: 固定样式的弹窗虽然样式固定,但你依然可以通过提供的 样式参数 (比如 cancelButtonStyle, textStyle, selectedTextStyle, width, height, transition 等) 来微调它们的外观和动画效果,让它们更贴合你的 App 风格!


搞定收工!


用户头像

Turing_010

关注

还未添加个人签名 2025-05-22 加入

还未添加个人简介

评论

发布
暂无评论
HarmonyOSNext一看就懂!ArkUI弹出框全方位攻略:从自定义到固定,玩转弹窗不迷糊!_Turing_010_InfoQ写作社区