鸿蒙项目实战(三):自定义弹窗开发实践
自定义弹窗选型
合理选择不同的系统能力实现弹窗,有利于提升应用开发效率,实现更好的功能需求,因此了解自定义弹窗的选型和差异非常重要。在应用开发中,为了选择出合适的弹窗选型,从使用场景上,需要重点关注以下两点:
- 弹窗与界面代码解耦
在开发业务逻辑时,例如遇到一些网络请求失败的场景,需要触发相应的弹窗提醒用户进行操作,由于在任何页面都有可能触发对应的弹窗,此时弹窗不是与某个页面相关联,这个情况下,就需要弹窗与界面的解耦。
- 弹窗在界面跳转后保留
在一些权限配置页,用户首次进入应用时会弹出权限配置弹窗,让用户进行操作,此时若点击跳转到隐私详情页面,返回后弹窗需要保留在页面上。
系统提供了四种不同的方式来实现自定义弹窗,分别是CustomDialog、promptAction、UIContext.getPromptAction、Navigation.Dialog,在开发业务时,需要结合每种弹窗的特点来选择弹窗。
- CustomDialog弹窗,必须在@Component struct内部定义,即在UI层创建控制器,当一个页面需要弹出多个自定义弹窗时,就需要创建对应个数的CustomDialogController,这会造成UI层代码冗余,无法做到弹窗与界面的解耦。
- promptAction弹窗,为了解决CustomDialog弹窗的问题,支持了UI元素复用机制@Builder,但依赖UI组件。
- UIContext.getPromptAction弹窗,基于promptAction弹窗演进而来,支持全局自定义弹窗,不依赖UI组件,依赖UIContext,支持在非页面文件中使用,弹窗内容支持动态修改,支持自定义弹窗圆角半径、大小和位置,适合在与页面解耦的全局弹窗、自定义弹窗显示和退出动画等场景下使用。
- Navigation.Dialog弹窗,基于Navigation路由形式,以Component组件页面存在于路由栈中,以进出栈的方式打开或关闭弹窗,可以实现弹窗与UI界面解耦,默认透明显示,适合在切换页面弹窗不消失场景下使用。
总结如下:
使用示例如下:
一、CustomerDialog
1、定义:
// 自定义提示弹框 // @CustomerDialog @CustomDialog export struct TipDialog { @State title: string = "提示" // 标题 @State message: string = ""; // 提示内容 @State cancelValue: string = "取消"; //取消按钮文案 @State confirmValue: string = "确定"; //确定按钮文案 cancel?: () => void // 取消事件 confirm?: () => void // 确定事件 controller: CustomDialogController = new CustomDialogController({ builder: TipDialog() }) build() { Column() { Text(this.title) .width('100%') .height(40) .textAlign(TextAlign.Center) .fontColor(Color.White) .backgroundColor($r('app.color.dialog_title_bg')) .borderRadius({ topLeft: 10, topRight: 10 }) Text(this.message) .height(70) .width('100%') .textAlign(TextAlign.Center) .backgroundColor(Color.White) Row() { Text(this.cancelValue) .layoutWeight(1) .backgroundColor(Color.White) .fontColor(Color.Black) .textAlign(TextAlign.Center) .height(40) .borderRadius({ bottomLeft: 10 }) .onClick(() => { if (this.cancel) { this.cancel() } }) Text(this.confirmValue) .layoutWeight(1) .backgroundColor($r('app.color.main_color')) .fontColor(Color.White) .textAlign(TextAlign.Center) .height(40) .borderRadius({ bottomRight: 10 }) .onClick(() => { if (this.confirm) { this.confirm() } }) } }.width('100%') } }
2、使用
import {TipDialog} from '../../components/dialogs/TipDialog' @Entry @Component struct More { // 有多少个弹框,就需要定义多少个CustomDialogController // 造成UI层代码冗余,无法做到弹窗与界面的解耦。 controller:CustomDialogController= new CustomDialogController({ builder : TipDialog({ message: '点击了内容', confirm: ()=>{ console.log('点击了确定') this.controller.close() }, cancel: ()=>{ console.log('点击了取消') this.controller.close() } }), alignment: DialogAlignment.Center, offset: { dx: 0, dy: -20 }, customStyle: false, width:'80%', cornerRadius:10, backgroundColor: 0xd9ffffff, }) showDialog(){ this.controller.open() } build() { Row() { Column() { Button('打开弹框') .fontWeight(FontWeight.Bold) .onClick(()=>{ this.showDialog() }) } .width('100%') } .height('100%') } }
二、UIContext.getPromptAction弹窗
1、定义
// 自定义弹框组件 // 使用UIContext.getPromptAction.openCustomDialog的方式 // https://developer.huawei.com/consumer/cn/doc/best-practices-V5/bpta-custome-dialog-development-practice-V5#section7466312192919 // https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/js-apis-arkui-uicontext-V5#opencustomdialog12 // 弹框可设置参数 export class DialogParms{ public title: string = "提示" // 标题 public message: string = "" // 提示内容 public cancelValue: string = "取消" // 取消按钮文案 public confirmValue: string = "确定" // 确定按钮文案 public cancel?: (() => void) | undefined // 取消事件 public confirm?: (() => void) | undefined // 确定事件 public setTitle(value: string):void { this.title = value } public setMessage(value: string):void { this.message = value } public setCancelValue(value: string):void { this.cancelValue = value } public setConfirmValue(value: string):void { this.confirmValue = value } public setCancel(value: (() => void) | undefined){ this.cancel = value } public setConfirm(value: (() => void) | undefined) { this.confirm = value } constructor(title:string) { this.title = title } } // 全局自定义函数 @Builder export function WarmDialog(parms:DialogParms){ Column() { Text(parms.title) .width('100%') .height(40) .textAlign(TextAlign.Center) .fontColor(Color.White) .backgroundColor($r('app.color.dialog_title_bg')) .borderRadius({topLeft:10,topRight:10}) Text(parms.message) .height(70) .width('100%') .textAlign(TextAlign.Center) .backgroundColor(Color.White) Row() { Text(parms.cancelValue) .layoutWeight(1) .backgroundColor(Color.White) .fontColor(Color.Black) .textAlign(TextAlign.Center) .height(40) .borderRadius({bottomLeft:10}) .onClick(()=>{ if (parms.cancel) { parms.cancel() } }) Text(parms.confirmValue) .layoutWeight(1) .backgroundColor($r('app.color.main_color')) .fontColor(Color.White) .textAlign(TextAlign.Center) .height(40) .borderRadius({bottomRight:10}) .onClick(()=>{ if (parms.confirm) { parms.confirm() } }) } }.width('80%') }
2、使用
import { ComponentContent, PromptAction, UIContext } from '@kit.ArkUI'; import {WarmDialog,DialogParms} from '../../components/dialogs/WarmDialog' @Entry @Component struct More { uiContext:UIContext = this.getUIContext() showDialog(){ let promptAction:PromptAction = this.uiContext.getPromptAction() let dialogParms = new DialogParms("警告") dialogParms.setTitle("警告") dialogParms.setMessage("这是警告内容") dialogParms.setCancel(()=>{ promptAction.closeCustomDialog(builderView) console.log('点击了取消') }) dialogParms.setConfirm(()=>{ promptAction.closeCustomDialog(builderView) console.log('点击了确定') }) let builderView = new ComponentContent( this.uiContext, wrapBuilder(WarmDialog),dialogParms ) promptAction.openCustomDialog(builderView,{alignment:DialogAlignment.Center},) } build() { Row() { Column() { Button('打开弹框') .fontWeight(FontWeight.Bold) .onClick(()=>{ this.showDialog() }) } .width('100%') } .height('100%') } }
作者:听着music睡
出处:http://www.cnblogs.com/xqxacm/
Android交流群:38197636
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。