本文转载自《OpenHarmony应用开发之自定义弹窗》,作者:zhushangyuan_

应用场景

在应用的使用和开发中,弹窗是一个很常见的场景,自定义弹窗又因为极高的自由度得以广泛应用。本文以橘子购物中一个应用更新提示的弹窗介绍OpenHarmony的自定义弹窗。

接口

自定义弹窗官方文档:自定义弹窗-弹窗-全局UI方法-组件参考(基于ArkTS的声明式开发范式)-ArkTS API参考-HarmonyOS应用开发

CustomDialogController是自定义弹窗对应的接口,详细介绍如下:

  1. CustomDialogController(value:{builder: CustomDialog, cancel?: () => void, autoCancel?: boolean, alignment?: DialogAlignment,
  2. offset?: Offset, customStyle?: boolean, gridCount?: number, maskColor?: ResourceColor,
  3. openAnimation?: AnimateParam, closeAnimation?: AnimateParam})

  

参数:

参数名

参数类型

必填

参数描述

builder

CustomDialog

自定义弹窗内容构造器。

cancel

() => void

点击遮障层退出时的回调。

autoCancel

boolean

是否允许点击遮障层退出。默认值:true

alignment

DialogAlignment

弹窗在竖直方向上的对齐方式。默认值:DialogAlignment.Default

offset

Offset

弹窗相对alignment所在位置的偏移量。

customStyle

boolean

弹窗容器样式是否自定义。默认值:false,弹窗容器的宽度根据栅格系统自适应,

不跟随子节点;高度自适应子节点,最大为窗口高度的90%;圆角为24vp。

gridCount8+

number

弹窗宽度占栅格宽度的个数。默认为按照窗口大小自适应,异常值按默认值处理,

最大栅格数为系统最大栅格数。

这其中最重要的就是builder,我们需要自己实现一个构造器,也就是这个弹窗的页面。

具体实现

定义CustomDialogController

首先,我们需要定义一个CustomDialogController:

  1. UpdateDialogController: CustomDialogController = new CustomDialogController({
  2. builder: UpdateDialog(),
  3. customStyle: true
  4. })

  

这个CustomDialogController就代表弹窗,UpdateDialog()是弹窗的具体实现,customStyle为ture就表示弹窗样式可以自定义。

设置调用时机

在这个场景中,我们想要每次打开应用的时候弹窗,其他时候不弹窗,我们需要在首页组件的aboutToAppear中加入以下代码:

  1. aboutToAppear() {
  2. if(AppStorage.Get('nowIndex') === undefined || AppStorage.Get('nowIndex') === 0){
  3. this.UpdateDialogController.open()
  4. }
  5. }

  

aboutToAppear函数的调用时机是创建自定义组件的新实例后,执行其build()函数之前,所以在首页组件的aboutToAppear加入CustomDialogController的打开开逻辑可使弹窗仅在应用打开的时候触发。

aboutToAppear参考文档:自定义组件的生命周期-组件参考(基于ArkTS的声明式开发范式)-ArkTS API参考-HarmonyOS应用开发

实现builder实例

实现实例可以直接在builder后面直接实现,也可以定义在其他文件中,然后通过调用的方式获取,本文以调用方式实现。

实例组件的定义前需加export才能暴露出去:

  1. export struct UpdateDialog {}

  

弹窗上所需的数据和获取也需要在在此处定义:

  1.  
  2. @CustomDialog
  3. export struct UpdateDialog {
  4. @State currentVersion: string = ''
  5. @State richTextData: string = ''
  6. @State lastVersion: string = ''
  7. @State updateContent: string = ''
  8. private context?: AbilityContext
  9. private customDialogController?: CustomDialogController
  10.  
  11. async aboutToAppear() {
  12. this.context = getContext(this) as AbilityContext
  13. this.richTextData = await dialogFeature.getRichTextData(this.context)
  14. Logger.info(TAG, `this.richTextData = ${this.richTextData}`)
  15. await this.getData()
  16. }
  17.  
  18. async getData() {
  19. try {
  20. this.currentVersion = await dialogFeature.getCurrentVersion()
  21. let requestResponseContent: RequestResponseContent = await dialogFeature.getLastVersion()
  22. if (requestResponseContent.content === null || requestResponseContent.content === undefined) {
  23. return
  24. }
  25. this.updateContent = requestResponseContent.content
  26. if (requestResponseContent.versionName === null || requestResponseContent.versionName === undefined) {
  27. return
  28. }
  29. this.lastVersion = requestResponseContent.versionName
  30. } catch (err) {
  31. Logger.info(TAG, `getApplicationVersion is fail`)
  32. }
  33. }
  34. ...

  

以上是应用升级所需的数据结构及部分数据获取。

弹窗具体实现

自定义弹窗的实现就是在原页面的基础上再加一层页面,页面内容自定义。

弹窗页面我们可以通过stack组件实现,stack组件会使容器内的子组件堆叠布局,使用stack的好处是可以添加一层遮罩效果。

  1. Stack() {
  2. // mask 遮罩层
  3. Column()
  4. .width('100%')
  5. .height('100%')
  6. .backgroundColor('#000000')
  7. .opacity(.4)
  8.  
  9. ...

  

以上代码在stack的第一层设置了backgroundColor和opacity属性,这样会产生如开始示意图的遮罩效果。

需要注意的是,需要在取消按钮的调用函数中关闭弹窗,具体代码如下:

  1. Button($r('app.string.cancel'))
  2. .onClick(() => {
  3. this.customDialogController.close()
  4. })

  

弹窗完整代码:

  1. build() {
  2. Stack() {
  3. // mask 遮罩层
  4. Column()
  5. .width('100%')
  6. .height('100%')
  7. .backgroundColor('#000000')
  8. .opacity(.4)
  9. Column() {
  10. Stack({ alignContent: Alignment.TopStart }) {
  11. Text($r('app.string.update_title'))
  12. .fontSize(30)
  13. .fontColor('#FFFFFF')
  14. .fontWeight(500)
  15. .margin({ top: 70, left: 76 })
  16.  
  17. Text(`V${(this.lastVersion || updateData.versionName)}`)
  18. .fontSize(16)
  19. .backgroundColor('#FFFFFF')
  20. .textAlign(TextAlign.Center)
  21. .fontColor('#E9304E')
  22. .borderRadius(20)
  23. .width(80)
  24. .aspectRatio(2.8)
  25. .margin({ top: 110, left: 76 })
  26.  
  27. Column() {
  28. // 富文本容器
  29. Scroll() {
  30. Column() {
  31. if (this.richTextData) {
  32. RichText((this.updateContent || this.richTextData))
  33. .width('100%')
  34. .height('100%')
  35. }
  36. }
  37. .width('100%')
  38. }
  39. .height(200)
  40.  
  41. Row() {
  42. Button($r('app.string.cancel'))
  43. .commonButtonStyle()
  44. .fontSize(20)
  45. .margin({ left: 10 })
  46. .fontColor('#E92F4F')
  47. .backgroundColor('rgba(0,0,0,0.05)')
  48. .margin({ right: 10 })
  49. .onClick(() => {
  50. this.customDialogController.close()
  51. })
  52. .key("cancel")
  53.  
  54. Button($r('app.string.update_now'))
  55. .commonButtonStyle()
  56. .fontSize(20)
  57. .margin({ right: 10 })
  58. .fontColor('#FFFFFF')
  59. .backgroundColor('#E92F4F')
  60. .margin({ left: 10 })
  61. .onClick(() => {
  62. this.customDialogController.close()
  63. })
  64. .key("Now")
  65. }
  66. .margin({ top: 30 })
  67. }
  68. .width('100%')
  69. .padding({ left: 25, right: 25 })
  70. .margin({ top: 230 })
  71. }
  72. .height(600)
  73. .width('100%')
  74. .backgroundImage($r('app.media.update'), ImageRepeat.NoRepeat)
  75. .backgroundImageSize(ImageSize.Contain)
  76. }
  77. .width(480)
  78. .padding({ left:16,right:16})
  79. }
  80. .width('100%')
  81. .height('100%')
  82. }

  

以上是弹窗完整代码,需要注意的是,本例并未实现应用升级的具体逻辑,所以升级按钮的操作也是关闭弹窗。

参考

本文供稿:https://gitee.com/JaysonLiu3

本例参考的官方文档:橘子购物

自定义弹窗官方文档

自定义组件的生命周期-aboutToAppear

层叠布局(Stack)-构建布局-开发布局-基于ArkTS的声明式开发范式-UI开发-开发-HarmonyOS应用开发

线性布局(Row/Column)-构建布局-开发布局-基于ArkTS的声明式开发范式-UI开发-开发-HarmonyOS应用开发

按钮(Button)-添加常用组件-添加组件-基于ArkTS的声明式开发范式-UI开发-开发-HarmonyOS应用开发

OpenHarmony应用开发之自定义弹窗的更多相关文章

  1. 微信小程序自定义弹窗wcPop插件|仿微信弹窗样式

    微信小程序自定义组件弹窗wcPop|小程序消息提示框|toast自定义模板弹窗 平时在开发小程序的时候,弹窗应用场景还是蛮广泛的,但是微信官方提供的弹窗比较有局限性,不能自定义修改.这个时候首先想到的 ...

  2. svelte组件:Svelte自定义弹窗Popup组件|svelte移动端弹框组件

    基于Svelte3.x自定义多功能svPopup弹出框组件(组件式+函数式) 前几天有分享一个svelte自定义tabbar+navbar组件,今天继续带来svelte自定义弹窗组件. svPopup ...

  3. ExtJs基础知识总结:自定义弹窗和ComboBox自动联想加载(四)

    概述 Extjs弹窗可以分为消息弹窗.对话框,这些弹窗的方式ExtJs自带的Ext.Msg.alert就已经可以满足简单消息提示,但是相对复杂的提示,比如如何将Ext.grid.Panel的控件显示嵌 ...

  4. iOS开发之自定义表情键盘(组件封装与自动布局)

    下面的东西是编写自定义的表情键盘,话不多说,开门见山吧!下面主要用到的知识有MVC, iOS开发中的自动布局,自定义组件的封装与使用,Block回调,CoreData的使用.有的小伙伴可能会问写一个自 ...

  5. xamarin UWP平台下 HUD 自定义弹窗

    在我的上一篇博客中我写了一个在xamarin的UWP平台下的自定义弹窗控件.在上篇文章中介绍了一种弹窗的写法,但在实际应用中发现了该方法的不足: 1.当弹窗出现后,我们拖动整个窗口大小的时候,弹窗的窗 ...

  6. android开发之自定义组件

    android开发之自定义组件 一:自定义组件: 我认为,自定义组件就是android给我们提供的的一个空白的可以编辑的图片,它帮助我们实现的我们想要的界面,也就是通过自定义组件我们可以把我们要登入的 ...

  7. 手机3D游戏开发:自定义Joystick的相关设置和脚本源码

    Joystick在手游开发中非常常见,也就是在手机屏幕上的虚拟操纵杆,但是Unity3D自带的Joystick贴图比较原始,所以经常有使用自定义贴图的需求. 下面就来演示一下如何实现自定义JoySti ...

  8. PHPCMS V9二次开发便捷自定义后台入口文件夹

    phpcms v9二次开发便捷自定义后台入口文件夹 最新发布的phpcms v9由于采用了mvc的设计模式,所以它的后台访问地址是固定的,虽然可以通过修改路由配置文件来实现修改,但每次都修改路由配置文 ...

  9. 详解iOS开发之自定义View

    iOS开发之自定义View是本文要将介绍的内容,iOS SDK中的View是UIView,我们可以很方便的自定义一个View.创建一个 Window-based Application程序,在其中添加 ...

  10. 如何开发使用自定义文件的OEM应用程序

    有关创建和使用自定义数据文件的详细信息,请参阅DISM应用程序包(.appx或.appxbundle)服务命令行选项. 了解如何开发使用自定义文件的应用程序,将信息从OEM传递到应用程序. 对于您为O ...

随机推荐

  1. 案例分享:Qt便携式致病菌快速检测仪(账号管理、实验过程、二维图表、历史数据、通讯管理、实验报告、中英文等等)

    需求   根据提供的用户原型设计.ui设计.通讯协议研发便携式致病菌快速检测仪器软件.  100%还原ui.   基本主功能(推荐visio:★★★☆☆,前期主流程需求整理)          Dem ...

  2. 【webserver 前置知识 02】Linux网络编程入门其一

    网络结构模式 C/S结构 服务器 - 客户机,即 Client - Server(C/S)结构.C/S 结构通常采取两层结构.服务器负责数据的管理,客户机负责完成与用户的交互任务.客户机是因特网上访问 ...

  3. 第119篇: JavaScript 类

    好家伙,我们先来复习一下   关于Java,类的三大特征: 1.封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏. 2.继承,继承性更 ...

  4. Html飞机大战(十五): 上线

    好家伙,   我的飞机大战部署上线了 胖虎的飞机大战 感兴趣的可以去玩一下     (怕有人接受不了这个背景,我还贴心的准备切换背景按钮,然而这并没有什么用) 现在,我们停下脚步,重新审视这个游戏   ...

  5. 面试必备:一线大厂Redis缓存设计规范与性能优化

    说在前面 你是否在使用Redis时,不清楚Redis应该遵循的设计规范而苦恼? 你是否在Redis出现性能问题时,不知道该如何优化而发愁? 你是否被面试官拷问过Redis的设计规范和性能优化而回答不出 ...

  6. ASP.NET Core 选项

    目录 1,选项接口 2,注入配置与IOptions 3,IOptionsSnapshot 首先要了解 ASP.NET Core 中的配置,请点击这里了解:https://www.cnblogs.com ...

  7. 图数据库 Nebula Graph 的代码变更测试覆盖率实践

    对于一个持续开发的大型工程而言,足够的测试是保证软件行为符合预期的有效手段,而不是仅仅依靠 code review 或者开发者自己的技术素质.测试的编写理想情况下应该完全定义软件的行为,但是通常情况都 ...

  8. Java 类的内部成员之五:内部类

    1 package com.bytezreo.innerclass; 2 3 /** 4 * 5 * @Description 类的内部成员之五:内部类 6 * @author Bytezero·zh ...

  9. 数据处理——IF函数求同时满足多个条件 多个条件满足一个以上

    以满足两个条件为例,满足多个条件类似 以如下案例为例进行说明: 一.IF公式同时满足多个条件 此例也可使用函数的嵌套,对于函数使用掌握不牢的新手,嵌套使用会有些困难,以下方法针对刚入门学习参考 1.利 ...

  10. STM32进入HardFault_Handler的调试方法

    在编写STM32程序代码时由于自己的粗心会发现有时候程序跑着跑着就进入了 HardFault_Handler中断,按照经验来说进入HardFault_Handler故障的原因主要有两个方面: 1:内存 ...