OpenHarmony——ets自定义弹窗UI组件封装

Posted OpenHarmony技术社区

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenHarmony——ets自定义弹窗UI组件封装相关的知识,希望对你有一定的参考价值。

作者:凌小凤

前言

​ 鸿蒙已经提供了全局UI方法自定义弹窗,本文是基于基础的自定义弹窗来实现提示消息弹窗、确认弹窗、输入弹窗的UI组件封装。

一、消息确认弹窗

首先看下效果:

1.1、首先先定义一个新的组件ConfirmDialog

@CustomDialog
export default struct ConfirmDialog 
    title: string = 
    content: string = 
    confirmFontColor: string = #E84026
    cancelFontColor:string = #0A59F7
    confirmText:string = 确认
    cancelText:string = 取消
    controller: CustomDialogController
    cancel: () => void
    confirm: () => void
    build()   

自定义确认弹窗可自定义传入的参数有:

可选参数:标题title(默认值:""),正文内容content(默认值:""),确认按钮字体颜色confirmFontColor(默认值:#E84026),取消按钮字体颜色cancelFontColor(默认值:#0A59F7),确认按钮文案(默认值:确认),取消按钮文案(默认值:取消)

必须参数:自定义弹窗控制器controller: CustomDialogController,确认按钮触发事件confirm(),取消按钮触发事件cancel()

1.2、标题、正文、按钮封装

一个确认弹窗组件主要由标题、正文等文本内容和取消、确认等按钮事件组成。下面将分别对文案和按钮通过@Extend装饰器进行封装。

@Extend装饰器将新的属性函数添加到内置组件上,如TextColumnButton等。通过@Extend装饰器可以快速定义并复用组件的自定义样式。

// 标题title与正文content自定义样式
@Extend(Text) function fancfontSize(fontSize: number) 
  .fontSize(fontSize)
  .width(100%)
  .fontColor(rgba(0, 0, 0, 0.86))
  .textAlign(TextAlign.Center)
  .padding( top: 15, bottom: 0, left: 8, right: 8 )
  .alignSelf(ItemAlign.Center)
  .margin(top: 16)


// 取消、确认按钮自定义样式
@Extend(Text) function fancBtn(fontColor: string) 
  .fontColor(fontColor)
  .backgroundColor(0xffffff)
  .width(188)
  .height(29)
  .fontSize(22)
  .textAlign(TextAlign.Center)

本示例仅标题与正文仅支持字体大小fontSize自定义,按钮仅支持按钮文案字体颜色fontColor自定义,其他通用属性皆是写定的,若想支持其他属性自定义,也可通过fancfontSize()添加新的参数。

其次,可以更进一步的对标题与正文通过@Builder装饰器进行封装,且通过是否传入title、content字段来判断是否展示对应文案。

@Builder装饰的方法用于定义组件的声明式UI描述,在 一个自定义组件内快速生成多个布局内容。 @Builder装饰方法的功能和语法规范与build函数相同。

// 文案样式
  @Builder TipTextStyle(tip:string, fontSize:number) 
    Text(tip)
      .fancfontSize(fontSize)
      .visibility(tip.length > 0 ? Visibility.Visible : Visibility.None)
  

注意:1、@Extend装饰器的内容必须写在ConfirmDialog组件外,且在@Extend装饰器声明的基础内置组件的 方法之前不能出现用/*多行注释(会报错),但可采用单行注释//。

​ 2、@Builder装饰器的内容要写在ConfirmDialog组件内,build()外 。

​ 3、@Builder装饰器声明的自定义组件内部可包含@Extend声明的自定义样式的基础组件,但是@Extend 内部不可包含@Builder装饰器声明的自定义组件。

1.3、ConfirmDialog组件完整代码

// 取消、确认按钮自定义样式
@Extend(Text) function fancBtn(fontColor: string) 
  .fontColor(fontColor)
  .backgroundColor(0xffffff)
  .width(188)
  .height(29)
  .fontSize(22)
  .textAlign(TextAlign.Center)

// 标题title与正文content自定义样式
@Extend(Text) function fancfontSize(fontSize: number) 
  .fontSize(fontSize)
  .width(100%)
  .fontColor(rgba(0, 0, 0, 0.86))
  .textAlign(TextAlign.Center)
  .padding( top: 15, bottom: 0, left: 8, right: 8 )
  .alignSelf(ItemAlign.Center)
  .margin(top: 16)

@CustomDialog
export default struct ConfirmDialog 
  title: string = 
  content: string = 
  confirmFontColor: string = #E84026
  cancelFontColor:string = #0A59F7
  confirmText:string = 确认
  cancelText:string = 取消
  controller: CustomDialogController
  cancel: () => void
  confirm: () => void
  // 标题、正文文案样式
  @Builder TipTextStyle(tip:string, fontSize:number) 
    Text(tip)
      .fancfontSize(fontSize)
      .visibility(tip.length > 0 ? Visibility.Visible : Visibility.None)
  

  build() 
    Column() 
      this.TipTextStyle(this.title, 28)
      this.TipTextStyle(this.content, 22)
      Flex( justifyContent: FlexAlign.SpaceAround ) 
        Text(this.cancelText)
          .fancBtn(this.cancelFontColor)
          .onClick(() => 
          this.controller.close()
          this.cancel()
        )
        Text(this.confirmText)
          .fancBtn(this.confirmFontColor)
          .onClick(() => 
            this.controller.close()
            this.confirm()
          )
      .margin( top: 30, bottom: 16, left: 16, right: 16 )
    
  

1.4、引用页面代码

import ConfirmDialog from ./components/dialog/ConfirmDialog.ets
@Entry
@Component
struct IndexComponent 
    // 确认弹窗
    private title: string = 标题
    private content: string = 此操作将永久删除该文件, 是否继续?
    private confirmText: string = 删除
    ConfirmDialogController: CustomDialogController = new CustomDialogController(
        builder: ConfirmDialog( cancel: this.onCancel, confirm: () => 
            this.onAccept()
        ,title:this.title, content: this.content),
        cancel: this.onCancel,
        autoCancel: true
    )
    // 点击取消按钮或遮罩层关闭弹窗
    onCancel() 
        console.info(取消,关闭弹窗)
    
    // 点击确认弹窗
    onAccept() 
        console.info(确认,关闭弹窗)
    
    build() 
        Scroll() 
            Column() 
                Text(确认弹窗)
                    .fontSize(24)
                    .width(300)
                    .height(60)
                    .border( width: 5, color: 0x317AF7, radius: 10, style: BorderStyle.Solid )
                    .margin(top: 20, bottom:10)
                    .textAlign(TextAlign.Center)
                    .onClick(() => 
                        this.ConfirmDialogController.open()
                    )
            
            .width(100%)
        
    

二、消息提示弹窗

首先看下效果:

2.1、首先先定义一个新的组件PromptDialog

@CustomDialog
export default struct PromptDialog 
    controller: CustomDialogController
    ancel: () => void
    build() 

至于标题、正文、按钮文案及按钮颜色的封装均与消息确认弹窗一样,同1.2所述。

2.2、PromptDialog组件完整代码

// 标题title与正文content自定义样式
@Extend(Text) function fancfontSize(fontSize: number) 
  .fontSize(fontSize)
  .width(100%)
  .fontColor(rgba(0, 0, 0, 0.86))
  .textAlign(TextAlign.Center)
  .padding( top: 15, bottom: 0, left: 8, right: 8 )
  .alignSelf(ItemAlign.Center)
  .margin(top: 16)

// 底部按钮自定义样式
@Extend(Text) function fancBtn(fontColor: string) 
  .backgroundColor(0xffffff)
  .fontColor(fontColor)
  .width(188)
  .height(29)
  .fontSize(22)
  .textAlign(TextAlign.Center)

@CustomDialog
export default struct PromptDialog 
  controller: CustomDialogController
  cancel: () => void
// 标题、正文文案样式
  @Builder TipTextStyle(tip:string, fontSize:number) 
    Text(tip)
      .fancfontSize(fontSize)
      .visibility(tip.length > 0 ? Visibility.Visible : Visibility.None)
  

  build() 
    Column() 
      this.TipTextStyle($s(strings.title), 28)
      this.TipTextStyle($s(strings.content), 22)
      Flex( justifyContent: FlexAlign.Center ) 
        Text($s(strings.confirm))
          .fancBtn(0x0A59F7)
          .onClick(() => 
            this.controller.close()
          )
      .margin( top: 30, bottom: 16 )
    
  

若标题title与正文content中的文案是固定的,可如此示例一样,可采用写入到resource中的zh_CN和en_US文件中,通过$s(strings.title)取值显示,若是动态获取的,可采用消息确认弹窗中传参方式。

2.3、引用页面代码

import PromptDialog from ./components/dialog/PromptDialog.ets
@Entry
@Component
struct IndexComponent 
    // 消息提示弹窗
    PromptDialogController: CustomDialogController = new CustomDialogController(
        builder: PromptDialog(),
        autoCancel: true
    )

    build() 
        Scroll() 
            Column() 
                Text(消息提示弹窗)
                    .fontSize(24)
                    .width(300)
                    .height(60)
                    .border( width: 5, color: 0x317AF7, radius: 10, style: BorderStyle.Solid )
                    .margin(top: 20, bottom:10)
                    .textAlign(TextAlign.Center)
                    .onClick(() => 
                        this.PromptDialogController.open()
                    )
            
            .width(100%)
        
    

三、消息输入弹窗

首先看下效果:

3.1、首先先定义一个新的组件InputDialog

export default struct InputDialog 
  title: string = 
  content: string = 
  @State inputString:string = 
  controller: CustomDialogController
  cancel: () => void
  confirm: (data) => void

  build() 

此示例讲述了子组件通过事件触发传参给父组件的方法,例如:在子组件用@state声明输入框内容inputString,通过confirm事件传参给父组件,可支持在父组件至于标题、正文、按钮文案及按钮颜色的封装均与消息确认弹窗一样,同1.2所述。

3.2、PromptDialog组件完整代码

// 取消、确认按钮自定义样式
@Extend(Text) function fancBtn(fontColor: string) 
  .fontColor(fontColor)
  .backgroundColor(0xffffff)
  .width(188)
  .height(29)
  .fontSize(22)
  .textAlign(TextAlign.Center)

// 标题title与正文content自定义样式
@Extend(Text) function fancfontSize(fontSize: number) 
  .fontSize(fontSize)
  .width(100%)
  .fontColor(rgba(0, 0, 0, 0.86))
  .textAlign(TextAlign.Start)
  .padding( top: 15, bottom: 0, left: 15, right: 15 )
  .margin(top: 16)

@CustomDialog
export default struct InputDialog 
  title: string = 
  content: string = 
  @State inputString:string = 
  controller: CustomDialogController
  cancel: () => void
  confirm: (data) => void
  // 文案样式
  @Builder TipTextStyle(tip:string, fontSize:number) 
    Text(tip)
      .fancfontSize(fontSize)
      .visibility(tip.length > 0 ? Visibility.Visible : Visibility.None)
  

  build() 
    Column() 
      this.TipTextStyle(this.title, 28)
      this.TipTextStyle(this.content, 22)
      // 输入框
      TextInput()
        .type(InputType.Normal)
        .enterKeyType(EnterKeyType.Next)
        .caretColor(Color.Green)
        .height(44)
        .margin(top: 20, left: 15; right:15)
        .alignSelf(ItemAlign.Center)
        .onChange((value: string) => 
          this.inputString = value
        )
      Flex( justifyContent: FlexAlign.SpaceAround ) 
        Text($s(strings.cancel))
          .fancBtn(#0A59F7)
          .onClick(() => 
          this.controller.close()
          this.cancel()
        )
        Text($s(strings.confirm))
          .fancBtn(#E84026)
          .onClick(() => 
            this.controller.close()
            console.log(inputString:+this.inputString)
            this.confirm(this.inputString)
          )
      .margin( top: 30, bottom: 16, left: 16, right: 16 )
    
  

3.3、引用页面代码

import InputDialog from ./components/dialog/InputDialog.ets
@Entry
@Component
struct IndexComponent 

// 输入弹窗
    private text: string = 提示
    private label: string = 请输入您的姓名
    InputDialogController: CustomDialogController = new CustomDialogController(
        builder: InputDialog( cancel: this.onCancel, confirm: (data) => 
            this.confirm(data)
        ,title: this.text, content: this.label ),
        cancel: this.onCancel,
        autoCancel: true
    )
// 点击取消按钮或遮罩层关闭弹窗
    onCancel() 
        console.info(取消,关闭输入弹窗)
    
// 点击确认弹窗
    confirm(data) 
        console.info(确认,关闭输入弹窗,data:+data)
    

    build() 
        Scroll() 
            Column() 
                Text(输入弹窗)
                    .fontSize(24)
                    .width(300)
                    .height(60)
                    .border( width: 5, color: 0x317AF7, radius: 10, style: BorderStyle.Solid )
                    .margin(top: 20, bottom:10)
                    .textAlign(TextAlign.Center)
                    .onClick(() => 
                        this.InputDialogController.open()
                    )
            
            .width(100%)
        
    

总结

​ 本文仅仅实现了三种自定义弹窗UI组件的封装(传参方式也讲解了多种,具体传参方式可视具体情况而定),待笔者优化了功能、代码后在来与大家分享, 在最后欢迎鸿蒙各位大佬指教。

更多原创内容请关注:深开鸿技术团队

入门到精通、技巧到案例,系统化分享HarmonyOS开发技术,欢迎投稿和订阅,让我们一起携手前行共建鸿蒙生态。

想了解更多关于鸿蒙的内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://ost.51cto.com/#bkwz

::: hljs-center

:::

以上是关于OpenHarmony——ets自定义弹窗UI组件封装的主要内容,如果未能解决你的问题,请参考以下文章

OpenHarmony ETS UI 组件封装之环形进度条

OpenHarmony eTS通用日志组件,写日志快一点

element-ui组件扩展 - 自定义confirm弹窗

angularjs 自定义弹窗指令

OpenHarmony——浅析ETS开发状态管理

React 如何设计一个弹窗组件