当前位置: 首页 > news >正文

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之打地鼠案例

需要素材的同学可以私信我 效果图&#xff1a; 上代码&#xff1a; <!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(滚动更新)存活探针&#xff08;livenessProb&#xff09;就绪探针(readiness) 4、ServiceClusterIPNodePortLoadBalancer 5、Ingres…...

EtherNet/IP开发:C++搭建基础模块,EtherNet/IP源代码

这里是CIP资料的协议层级图&#xff0c;讲解协议构造。 ODVA&#xff08;www.ODVA.org&#xff09;成立于1995年&#xff0c;是一个全球性协会&#xff0c;其成员包括世界领先的自动化公司。结合其成员的支持&#xff0c;ODVA的使命是在工业自动化中推进开放、可互操作的信息和…...

Django(九)

1. 用户登录-Cookie和Session 什么是cookie和session&#xff1f; 发送HTTP请求或者HTTPS请求(无状态&短连接) http://127.0.0.1:8000/admin/list/ https://127.0.0.1:8000/admin/list/http无状态短连接&#xff1a;一次请求响应之后断开连接&#xff0c;再发请求重新连…...

解决Android Studio Unexpected tokens (use ; to separate expressions on the same line)

[TOC](Unexpected tokens (use ; to separate expressions on the same line)) 问题描述&#xff1a;Unexpected tokens (use ; to separate expressions on the same line) 原因&#xff1a;Android Studio 更新到最新的版本之后&#xff0c;gradle工程目录结构发生改变 问…...

【云原生】Docker网络模式和Cgroup资源限制

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

实战:加密传输数据解密

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

前端开发提高效率的两大工具

一、浏览器中的开发者工具 怎么启动开发者工具&#xff1f; 在浏览器中按下F12或者鼠标右键点击检查 怎么利用&#xff08;常用的几点&#xff09;&#xff1f; 1、元素 点击标红的图标可以用于在页面选择元素&#xff0c;同时右侧会找到元素在前端代码中的位置 点击下方红…...

探索设计模式的魅力:深入理解面向对象设计的深层原则与思维

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

【Py/Java/C++三种语言详解】LeetCode每日一题240122【贪心】LeetCode670、最大交换

文章目录 题目链接题目描述解题思路为什么是贪心一个带图的例子 代码pythonjavacpp时空复杂度 华为OD算法/大厂面试高频题算法练习冲刺训练 题目链接 LeetCode670、最大交换 题目描述 给定一个非负整数数组 nums 和一个整数 k &#xff0c;你需要将这个数组分成 k 个非空的连…...

Linux/Doctor

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

嵌入式linux学习之系统烧录

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

JVM-初始JVM

什么是JVM JVM 全称是 Java Virtual Machine&#xff0c;中文译名 Java虚拟机。JVM 本质上是一个运行在计算机上的程序&#xff0c;他的职责是运行Java字节码文件。 Java源代码执行流程如下&#xff1a; JVM的功能 1 - 解释和运行 2 - 内存管理 3 - 即时编译 解释和运行 解释…...

EXCEL VBA网抓技巧-复制网页表格,不用遍历单元格

EXCEL VBA网抓技巧-复制网页表格&#xff0c;不用遍历单元格 对应表格复制 Sub tableTest()Set winhttp CreateObject("winhttp.WinHttpRequest.5.1")Set HTML CreateObject("htmlfile")Set oWindow HTML.ParentWindowUrl "https://www.taiwanlo…...

动态规划——炮兵回城【集训笔记】

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

低成本扫码点餐:1000元全包

在数字化时代&#xff0c;扫码点餐已经成为餐饮行业的标配。然而&#xff0c;对于许多小规模或初创的餐饮企业来说&#xff0c;开发一套完整的扫码点餐系统是一项成本高昂的任务。今天&#xff0c;我们将向您介绍一个低成本、高效的方法&#xff0c;让您用1000块钱轻松搞定一套…...

浅谈 React Hooks

React Hooks 是 React 16.8 引入的一组 API&#xff0c;用于在函数组件中使用 state 和其他 React 特性&#xff08;例如生命周期方法、context 等&#xff09;。Hooks 通过简洁的函数接口&#xff0c;解决了状态与 UI 的高度解耦&#xff0c;通过函数式编程范式实现更灵活 Rea…...

日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻

在如今就业市场竞争日益激烈的背景下&#xff0c;越来越多的求职者将目光投向了日本及中日双语岗位。但是&#xff0c;一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧&#xff1f;面对生疏的日语交流环境&#xff0c;即便提前恶补了…...

DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径

目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

Docker 运行 Kafka 带 SASL 认证教程

Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明&#xff1a;server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...

Linux-07 ubuntu 的 chrome 启动不了

文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了&#xff0c;报错如下四、启动不了&#xff0c;解决如下 总结 问题原因 在应用中可以看到chrome&#xff0c;但是打不开(说明&#xff1a;原来的ubuntu系统出问题了&#xff0c;这个是备用的硬盘&a…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战

“&#x1f916;手搓TuyaAI语音指令 &#x1f60d;秒变表情包大师&#xff0c;让萌系Otto机器人&#x1f525;玩出智能新花样&#xff01;开整&#xff01;” &#x1f916; Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制&#xff08;TuyaAI…...

C++八股 —— 单例模式

文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全&#xff08;Thread Safety&#xff09; 线程安全是指在多线程环境下&#xff0c;某个函数、类或代码片段能够被多个线程同时调用时&#xff0c;仍能保证数据的一致性和逻辑的正确性&#xf…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

企业如何增强终端安全?

在数字化转型加速的今天&#xff0c;企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机&#xff0c;到工厂里的物联网设备、智能传感器&#xff0c;这些终端构成了企业与外部世界连接的 “神经末梢”。然而&#xff0c;随着远程办公的常态化和设备接入的爆炸式…...

C++使用 new 来创建动态数组

问题&#xff1a; 不能使用变量定义数组大小 原因&#xff1a; 这是因为数组在内存中是连续存储的&#xff0c;编译器需要在编译阶段就确定数组的大小&#xff0c;以便正确地分配内存空间。如果允许使用变量来定义数组的大小&#xff0c;那么编译器就无法在编译时确定数组的大…...