关闭

OpenHarmony应用开发之自定义弹窗

发表于:2023-8-18 09:44

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:zhushangyuan_    来源:网络

  应用场景
  在应用的使用和开发中,弹窗是一个很常见的场景,自定义弹窗又因为极高的自由度得以广泛应用。本文以橘子购物中一个应用更新提示的弹窗介绍OpenHarmony的自定义弹窗。
  接口
  自定义弹窗官方文档:自定义弹窗-弹窗-全局UI方法-组件参考(基于ArkTS的声明式开发范式)-ArkTS API参考-HarmonyOS应用开发。
  CustomDialogController是自定义弹窗对应的接口,详细介绍如下:
  CustomDialogController(value:{builder: CustomDialog, cancel?: () => void, autoCancel?: boolean, alignment?: DialogAlignment, 
                        offset?: Offset, customStyle?: boolean, gridCount?: number, maskColor?: ResourceColor, 
                        openAnimation?: AnimateParam, closeAnimation?: AnimateParam})
  参数:
  这其中最重要的就是builder,我们需要自己实现一个构造器,也就是这个弹窗的页面。
  具体实现
  定义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参考文档:自定义组件的生命周期-组件参考(基于ArkTS的声明式开发范式)-ArkTS API参考-HarmonyOS应用开发。
  实现builder实例
  实现实例可以直接在builder后面直接实现,也可以定义在其他文件中,然后通过调用的方式获取,本文以调用方式实现。
  实例组件的定义前需加export才能暴露出去:
  export struct UpdateDialog {}
  弹窗上所需的数据和获取也需要在在此处定义:
  @CustomDialog
  export struct UpdateDialog {
    @State currentVersion: string = ''
    @State richTextData: string = ''
    @State lastVersion: string = ''
    @State updateContent: string = ''
    private context?: AbilityContext
    private customDialogController?: CustomDialogController
    async aboutToAppear() {
      this.context = getContext(this) as AbilityContext
      this.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.content
        if (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%')
  }
  以上是弹窗完整代码,需要注意的是,本例并未实现应用升级的具体逻辑,所以升级按钮的操作也是关闭弹窗。
  本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号