HarmonyOS 鸿蒙应用开发( 六、实现自定义弹窗CustomDialog)
自定义弹窗(CustomDialog)可用于广告、中奖、警告、软件更新等与用户交互响应操作。开发者可以通过CustomDialogController类显示自定义弹窗。具体用法请参考自定义弹窗。
在应用的使用和开发中,弹窗是一个很常见的场景,自定义弹窗又因为极高的自由度得以广泛应用。本文以橘子购物中一个应用更新提示的弹窗介绍OpenHarmony的自定义弹窗。
简单使用
1.1 创建自定义弹窗
使用@CustomDialog装饰器装饰自定义弹窗。
@CustomDialog装饰器用于装饰自定义弹框,此装饰器内进行自定义内容(也就是弹框内容)。
@CustomDialog
struct CustomDialogExample {controller: CustomDialogControllerbuild() {Column() {Text('我是内容').fontSize(20).margin({ top: 10, bottom: 10 })}}
}
1.2 创建构造器,与装饰器呼应相连
在创建好自定义弹窗之后,我们New出来它的对象,他的类型是CustomDialogController。
dialogController: CustomDialogController = new CustomDialogController({builder: CustomDialogExample({}),
})
CustomDialogController参数详解
接口函数原型:
CustomDialogController(value:{builder: CustomDialog, cancel?: () => void, autoCancel?: boolean, alignment?: DialogAlignment, offset?: Offset, customStyle?: boolean, gridCount?: number, maskColor?: ResourceColor, openAnimation?: AnimateParam, closeAnimation?: AnimateParam})
这其中最重要的就是builder,我们需要自己实现一个构造器,也就是这个弹窗的页面。上述简单示例的CustomDialogExample,就是一个弹窗页面。
简单示例代码:
// xxx.ets
@CustomDialog
struct CustomDialogExample {@Link textValue: string@Link inputValue: stringcontroller: CustomDialogController// 若尝试在CustomDialog中传入多个其他的Controller,以实现在CustomDialog中打开另一个或另一些CustomDialog,那么此处需要将指向自己的controller放在最后cancel: () => voidconfirm: () => voidbuild() {Column() {Text('Change text').fontSize(20).margin({ top: 10, bottom: 10 })TextInput({ placeholder: '', text: this.textValue }).height(60).width('90%').onChange((value: string) => {this.textValue = value})Text('Whether to change a text?').fontSize(16).margin({ bottom: 10 })Flex({ justifyContent: FlexAlign.SpaceAround }) {Button('cancel').onClick(() => {this.controller.close()this.cancel()}).backgroundColor(0xffffff).fontColor(Color.Black)Button('confirm').onClick(() => {this.inputValue = this.textValuethis.controller.close()this.confirm()}).backgroundColor(0xffffff).fontColor(Color.Red)}.margin({ bottom: 10 })}// dialog默认的borderRadius为24vp,如果需要使用border属性,请和borderRadius属性一起使用。}
}@Entry
@Component
struct CustomDialogUser {@State textValue: string = ''@State inputValue: string = 'click me'dialogController: CustomDialogController = new CustomDialogController({builder: CustomDialogExample({cancel: this.onCancel,confirm: this.onAccept,textValue: $textValue,inputValue: $inputValue}),cancel: this.existApp,autoCancel: true,alignment: DialogAlignment.Bottom,offset: { dx: 0, dy: -20 },gridCount: 4,customStyle: false})// 在自定义组件即将析构销毁时将dialogControlle删除和置空aboutToDisappear() {delete this.dialogController, // 删除dialogControllerthis.dialogController = undefined // 将dialogController置空}onCancel() {console.info('Callback when the first button is clicked')}onAccept() {console.info('Callback when the second button is clicked')}existApp() {console.info('Click the callback in the blank area')}build() {Column() {Button(this.inputValue).onClick(() => {if (this.dialogController != undefined) {this.dialogController.open()}}).backgroundColor(0x317aff)}.width('100%').margin({ top: 5 })}
}
升级弹窗界面示例
定义CustomDialogController
首先,我们需要定义一个CustomDialogController:
UpdateDialogController: CustomDialogController = new CustomDialogController({builder: UpdateDialog(),customStyle: true
})
这个CustomDialogController就代表弹窗,UpdateDialog()是弹窗的具体实现,customStyle为ture就表示弹窗样式可以自定义。
设置调用时机
在这个场景中,我们想要每次打开应用的时候弹窗,其他时候不弹窗,我们需要在首页组件的aboutToAppear中加入以下代码:
aboutToAppear() {if(AppStorage.Get('nowIndex') === undefined || AppStorage.Get('nowIndex') === 0){this.UpdateDialogController.open()}
}
aboutToAppear函数的调用时机是创建自定义组件的新实例后,执行其build()函数之前,所以在首页组件的aboutToAppear加入CustomDialogController的打开开逻辑可使弹窗仅在应用打开的时候触发。
aboutToAppear参考文档:自定义组件的生命周期
实现builder实例
实现实例可以直接在builder后面直接实现,也可以定义在其他文件中,然后通过调用的方式获取,本文以调用方式实现。
实例组件的定义前需加export才能暴露出去:
export struct UpdateDialog {}
@CustomDialog
export struct UpdateDialog {@State currentVersion: string = ''@State richTextData: string = ''@State lastVersion: string = ''@State updateContent: string = ''private context?: AbilityContextprivate customDialogController?: CustomDialogControllerasync aboutToAppear() {this.context = getContext(this) as AbilityContextthis.richTextData = await dialogFeature.getRichTextData(this.context)Logger.info(TAG, `this.richTextData = ${this.richTextData}`)await this.getData()}async getData() {try {this.currentVersion = await dialogFeature.getCurrentVersion()let requestResponseContent: RequestResponseContent = await dialogFeature.getLastVersion()if (requestResponseContent.content === null || requestResponseContent.content === undefined) {return}this.updateContent = requestResponseContent.contentif (requestResponseContent.versionName === null || requestResponseContent.versionName === undefined) {return}this.lastVersion = requestResponseContent.versionName} catch (err) {Logger.info(TAG, `getApplicationVersion is fail`)}}...
弹窗具体实现
自定义弹窗的实现就是在原页面的基础上再加一层页面,页面内容自定义。
弹窗页面我们可以通过stack组件实现,stack组件会使容器内的子组件堆叠布局,使用stack的好处是可以添加一层遮罩效果。
Stack() {// mask 遮罩层Column().width('100%').height('100%').backgroundColor('#000000').opacity(.4)...
以上代码在stack的第一层设置了backgroundColor和opacity属性,这样会产生如开始示意图的遮罩效果。
需要注意的是,需要在取消按钮的调用函数中关闭弹窗,具体代码如下:
Button($r('app.string.cancel')).onClick(() => {this.customDialogController.close()})
弹窗界面完整代码
build() {Stack() {// mask 遮罩层Column().width('100%').height('100%').backgroundColor('#000000').opacity(.4)Column() {Stack({ alignContent: Alignment.TopStart }) {Text($r('app.string.update_title')).fontSize(30).fontColor('#FFFFFF').fontWeight(500).margin({ top: 70, left: 76 })Text(`V${(this.lastVersion || updateData.versionName)}`).fontSize(16).backgroundColor('#FFFFFF').textAlign(TextAlign.Center).fontColor('#E9304E').borderRadius(20).width(80).aspectRatio(2.8).margin({ top: 110, left: 76 })Column() {// 富文本容器Scroll() {Column() {if (this.richTextData) {RichText((this.updateContent || this.richTextData)).width('100%').height('100%')}}.width('100%')}.height(200)Row() {Button($r('app.string.cancel')).commonButtonStyle().fontSize(20).margin({ left: 10 }).fontColor('#E92F4F').backgroundColor('rgba(0,0,0,0.05)').margin({ right: 10 }).onClick(() => {this.customDialogController.close()}).key("cancel")Button($r('app.string.update_now')).commonButtonStyle().fontSize(20).margin({ right: 10 }).fontColor('#FFFFFF').backgroundColor('#E92F4F').margin({ left: 10 }).onClick(() => {this.customDialogController.close()}).key("Now")}.margin({ top: 30 })}.width('100%').padding({ left: 25, right: 25 }).margin({ top: 230 })}.height(600).width('100%').backgroundImage($r('app.media.update'), ImageRepeat.NoRepeat).backgroundImageSize(ImageSize.Contain)}.width(480).padding({ left: 16, right: 16 })}.width('100%').height('100%')
}
参考
本文供稿:刘家辉 (JaysonLiu3) - Gitee.com
本例参考的官方文档:橘子购物
自定义弹窗官方文档
自定义组件的生命周期-aboutToAppear
其他资源
层叠布局(Stack)-构建布局-开发布局-基于ArkTS的声明式开发范式-UI开发-开发-HarmonyOS应用开发
线性布局(Row/Column)-构建布局-开发布局-基于ArkTS的声明式开发范式-UI开发-开发-HarmonyOS应用开发
按钮(Button)-添加常用组件-添加组件-基于ArkTS的声明式开发范式-UI开发-开发-HarmonyOS应用开发
【鸿蒙软件开发】自定义弹窗(CustomDialog)_harmonyos developer自定义弹框-CSDN博客
免费的api接口网站有哪些? - 知乎
文档中心
applications_app_samples: We provide a series of app samples to help you quickly get familiar with the APIs and app development process of the OpenHarmony SDKs. | 为帮助开发者快速熟悉OpenHarmony SDK所提供的API和应用开发流程,我们提供了一系列的应用示例
Codelabs: 分享知识与见解,一起探索HarmonyOS的独特魅力。
相关文章:

HarmonyOS 鸿蒙应用开发( 六、实现自定义弹窗CustomDialog)
自定义弹窗(CustomDialog)可用于广告、中奖、警告、软件更新等与用户交互响应操作。开发者可以通过CustomDialogController类显示自定义弹窗。具体用法请参考自定义弹窗。 在应用的使用和开发中,弹窗是一个很常见的场景,自定义弹窗…...
# Java NIO(一)FileChannel
Java NIO 1.BIO与NIO的区别 BIO为阻塞IO,NIO为非阻塞IO。 BIONIOJAVA1.4之前Java 1.4之后面向流:以byte为单位处理数据面向块:以块为单位处理数据同步阻塞同步非阻塞无选择器(Selector) 1.1NIO的核心组成部分 Cha…...

[嵌入式软件][启蒙篇][仿真平台] STM32F103实现串口输出输入、ADC采集
上一篇:[嵌入式软件][启蒙篇][仿真平台] STM32F103实现LED、按键 文章目录 一、串口输出(1) 简介(2) 示例代码(3) 仿真效果 二、串口输入(1) 简介(2) 示例代码(3) 仿真效果 三、ADC采集(1) 简介(2) 采集电压(3) 示例代码(电压)(4) 仿真效果 …...

Deepin基本环境查看(四)【硬盘/分区、文件系统、硬连接/软连接】
Linux操作系统(Deepin、Ubuntu)操作系统中,硬盘分区的管理与Windows操作系统不同; 在Linux系统中维护着一个统一的文件目录体系,而硬盘和分区是以资源的形式由操作系统挂接和调度;此外Linux系统中连接(硬连…...

JS之打地鼠案例
需要素材的同学可以私信我 效果图: 上代码: <!DOCTYPE html> <html> <head><meta charset"utf-8"><title></title><style>* {margin: 0;padding: 0;}.box {position: relative;width: 320px;heigh…...

Kubernetes入门
k8s相关基础知识 文章目录 k8s相关基础知识1、Container2、PodPod 与 Container 的不同Pod 其它命令 3、Deployment扩容升级版本Rolling update(滚动更新)存活探针(livenessProb)就绪探针(readiness) 4、ServiceClusterIPNodePortLoadBalancer 5、Ingres…...

EtherNet/IP开发:C++搭建基础模块,EtherNet/IP源代码
这里是CIP资料的协议层级图,讲解协议构造。 ODVA(www.ODVA.org)成立于1995年,是一个全球性协会,其成员包括世界领先的自动化公司。结合其成员的支持,ODVA的使命是在工业自动化中推进开放、可互操作的信息和…...

Django(九)
1. 用户登录-Cookie和Session 什么是cookie和session? 发送HTTP请求或者HTTPS请求(无状态&短连接) http://127.0.0.1:8000/admin/list/ https://127.0.0.1:8000/admin/list/http无状态短连接:一次请求响应之后断开连接,再发请求重新连…...
解决Android Studio Unexpected tokens (use ; to separate expressions on the same line)
[TOC](Unexpected tokens (use ; to separate expressions on the same line)) 问题描述:Unexpected tokens (use ; to separate expressions on the same line) 原因:Android Studio 更新到最新的版本之后,gradle工程目录结构发生改变 问…...

【云原生】Docker网络模式和Cgroup资源限制
目录 一、Docker 网络实现原理 二、Docker 的网络模式 #网络模式详解: 第一种:host模式 第二种:bridge模式 第三种:container模式 第四种:none模式 第五种:自定义网络 三、Cgroup资源控制 第一种&a…...

实战:加密传输数据解密
前言 下面将分享一些实际的渗透测试经验,帮助你应对在测试中遇到的数据包内容加密的情况。我们将以实战为主,技巧为辅,进入逆向的大门。 技巧 开局先讲一下技巧,掌握好了技巧,方便逆向的时候可以更加快速的找到关键…...

前端开发提高效率的两大工具
一、浏览器中的开发者工具 怎么启动开发者工具? 在浏览器中按下F12或者鼠标右键点击检查 怎么利用(常用的几点)? 1、元素 点击标红的图标可以用于在页面选择元素,同时右侧会找到元素在前端代码中的位置 点击下方红…...

探索设计模式的魅力:深入理解面向对象设计的深层原则与思维
如何同时提高一个软件系统的可维护性 和 可复用性是面向对象对象要解决的核心问题。 通过学习和应用设计模式,可以更加深入地理解面向对象的设计理念,从而帮助设计师改善自己的系统设计。但是,设计模式并不能够提供具有普遍性的设计指导原则。…...

【Py/Java/C++三种语言详解】LeetCode每日一题240122【贪心】LeetCode670、最大交换
文章目录 题目链接题目描述解题思路为什么是贪心一个带图的例子 代码pythonjavacpp时空复杂度 华为OD算法/大厂面试高频题算法练习冲刺训练 题目链接 LeetCode670、最大交换 题目描述 给定一个非负整数数组 nums 和一个整数 k ,你需要将这个数组分成 k 个非空的连…...

Linux/Doctor
Enumeration nmap 已知目标开放了22,80,8089端口,扫描详细情况如下 可以看到对外开放了22,80,8089三个端口 TCP/80 SSTI 访问80端口,有一个infodoctors.htb的电子邮件,点击其他的也没有什么反应,猜测有可能需要域名访问 在/et…...

嵌入式linux学习之系统烧录
1.所需文件 1. 开发板为正点原子stm32mp157,文件可按照linux驱动教程编译,也可在正点原子文档->08、系统镜像\02、出厂系统镜像中找到: 2.烧录 1.拨码开关为000(usb启动),otg接口接入虚拟机,打开stm32cubeProgrammer: 2.页面…...

JVM-初始JVM
什么是JVM JVM 全称是 Java Virtual Machine,中文译名 Java虚拟机。JVM 本质上是一个运行在计算机上的程序,他的职责是运行Java字节码文件。 Java源代码执行流程如下: JVM的功能 1 - 解释和运行 2 - 内存管理 3 - 即时编译 解释和运行 解释…...
EXCEL VBA网抓技巧-复制网页表格,不用遍历单元格
EXCEL VBA网抓技巧-复制网页表格,不用遍历单元格 对应表格复制 Sub tableTest()Set winhttp CreateObject("winhttp.WinHttpRequest.5.1")Set HTML CreateObject("htmlfile")Set oWindow HTML.ParentWindowUrl "https://www.taiwanlo…...

动态规划——炮兵回城【集训笔记】
题目描述 游戏盘面是一个m行n列的方格矩阵,将每个方格用坐标表示,行坐标从下到上依次递增,列坐标从左至右依次递增,左下角方格的坐标为(1,1),则右上角方格的坐标为(m,n)。 游戏结束盘上只剩下一枚炮兵没有回到城池中&a…...

低成本扫码点餐:1000元全包
在数字化时代,扫码点餐已经成为餐饮行业的标配。然而,对于许多小规模或初创的餐饮企业来说,开发一套完整的扫码点餐系统是一项成本高昂的任务。今天,我们将向您介绍一个低成本、高效的方法,让您用1000块钱轻松搞定一套…...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

铭豹扩展坞 USB转网口 突然无法识别解决方法
当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...

深度学习在微纳光子学中的应用
深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...

.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...

对WWDC 2025 Keynote 内容的预测
借助我们以往对苹果公司发展路径的深入研究经验,以及大语言模型的分析能力,我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际,我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测,聊作存档。等到明…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面
代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口(适配服务端返回 Token) export const login async (code, avatar) > {const res await http…...
什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南
文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果
RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文全面剖析RNN核心原理,深入讲解梯度消失/爆炸问题,并通过LSTM/GRU结构实现解决方案,提供时间序列预测和文本生成…...