请参考demo://Index.ets import { Test1Dialog } from './Test1Dialog'; @Entry @Component struct Index { build() { Column() { Button('弹窗1') .onClick(() => { const dialog1 = new Test1Dialog(this.getUIContext()) dialog1.setAlignment(DialogAlignment.Bottom) // 方式1:给Dialog设置动画 dialog1.setTransition(TransitionEffect.asymmetric(TransitionEffect.move(TransitionEdge.BOTTOM), TransitionEffect.move(TransitionEdge.BOTTOM)).animation({ duration: 1000 })) dialog1.show() dialog1.refresh() }) } .justifyContent(FlexAlign.Center) .height('100%') .width('100%') } } //BaseDialog.ets import { ComponentContent, PromptAction, uiObserver } from '@kit.ArkUI' import json from '@ohos.util.json' export abstract class BaseDialog<P extends Object> { protected uiContext: UIContext private weakUIContext: WeakRef<UIContext> private action: PromptAction private content: ComponentContent<P> protected isShowing = false private canceledOnTouchOutside = true // 点击弹窗外面是否关闭弹窗 private canceledOnPressBack = true // 手势返回或者返回按钮关闭弹窗 private alignment = DialogAlignment.Center protected params: P private currentPage: string private isOn = false private dismissByUser = false private maskColor: ResourceColor = $r('sys.color.mask_fourth') private showInSubWindow = false private isModel = true private transition?: TransitionEffect constructor(uiContext: UIContext) { this.currentPage = uiContext.getRouter().getState().path + uiContext.getRouter().getState().name this.weakUIContext = new WeakRef(uiContext) this.uiContext = this.weakUIContext.deref()! this.action = uiContext.getPromptAction() this.params = this.createParams() this.content = new ComponentContent(uiContext, this.createWrappedBuilder(), this.params) } setCanceledOnTouchOutside(cancel: boolean) { this.canceledOnTouchOutside = cancel return this } setCanceledOnPressBack(cancel: boolean) { this.canceledOnPressBack = cancel return this } setAlignment(alignment: DialogAlignment) { this.alignment = alignment return this } setMaskColor(color: ResourceColor) { this.maskColor = color return this } setShowInSubWindow(inSub: boolean) { this.showInSubWindow = inSub return this } setTransition(transition: TransitionEffect) { this.transition = transition } setModel(model: boolean) { this.isModel = model return this } show(params?: P) { if (!this.isShowing) { this._show() } if (params) { this.update(params) } } private routerPageUpdate(info: RouterPageInfo) { if (this.currentPage !== info.name) { return } if (info.state === uiObserver.RouterPageState.ON_PAGE_SHOW) { if (!this.dismissByUser) { this.show() } } else if (info.state === uiObserver.RouterPageState.ON_PAGE_HIDE) { this._dismiss() // 在弹窗上打开了新的页面,自动关闭弹窗,等下次再回到弹窗页面时再次打开弹窗 } } update(params: P) { if (!this.isShowing) { return } this.params = params this.content.update(params) } dismiss() { this.dismissByUser = true this.uiContext.getUIObserver().off("routerPageUpdate") this.isOn = false this._dismiss() } private _show() { this.dismissByUser = false this.isShowing = true if (!this.isOn) { this.isOn = true this.uiContext.getUIObserver().on("routerPageUpdate", (info) => { this.routerPageUpdate(info) }) } this.action.openCustomDialog(this.content, { alignment: this.alignment, isModal: this.isModel, maskColor: this.maskColor, showInSubWindow: this.showInSubWindow, transition: this.transition, // transition: TransitionEffect.asymmetric(TransitionEffect.move(TransitionEdge.BOTTOM), // TransitionEffect.move(TransitionEdge.BOTTOM)) // .animation({ duration: 1000 }), onWillDismiss: (dialogAction: DismissDialogAction) => { console.log(`dialog_action : ${json.stringify(dialogAction)}`) if (dialogAction.reason === DismissReason.PRESS_BACK && this.canceledOnPressBack) { this.dismiss() } if (dialogAction.reason === DismissReason.TOUCH_OUTSIDE && this.canceledOnTouchOutside) { this.dismiss() } }, onDidAppear: () => { this.isShowing = true }, onDidDisappear: () => { this.isShowing = false } }) } private _dismiss() { try { this.isShowing = false this.action.closeCustomDialog(this.content) } catch (error) { console.error(`OpenCustomDialog message : ${error}`); } } abstract createWrappedBuilder(): WrappedBuilder<[P]> abstract createParams(): P } //Test1Dialog.ets import { BaseDialog } from './BaseDialog'; export class Test1Dialog extends BaseDialog<NumberParams> { private intervalId: number = -1 createWrappedBuilder(): WrappedBuilder<[NumberParams]> { return wrapBuilder(buildTestDialog) } createParams(): NumberParams { return new NumberParams(this, 0) } refresh() { if (this.intervalId != -1) { clearInterval(this.intervalId) } this.intervalId = setInterval(() => { this.params.value++ this.update(this.params) }, 1000) } } @Builder function buildTestDialog(params: NumberParams) { TestDialogContent({ params: params }) } /** * 弹窗UI */ @Component struct TestDialogContent { @ObjectLink params: NumberParams build() { Column() { Text(this.params?.value?.toString()) .fontSize(80) Row() { Button('CLOSE') .onClick(() => { this.params?.dialog.dismiss() }) } .width('100%') .justifyContent(FlexAlign.SpaceAround) } .width('100%') .height('30%') .backgroundColor(Color.White) .borderRadius(20) .justifyContent(FlexAlign.SpaceEvenly) .transition(TransitionEffect.asymmetric(TransitionEffect.move(TransitionEdge.BOTTOM), TransitionEffect.move(TransitionEdge.BOTTOM)).animation({ duration: 1000 })) } } /** * 传递给弹窗UI中的参数,参数变化可驱动UI变化 */ @Observed export class NumberParams { dialog: Test1Dialog value: number constructor(dialog: Test1Dialog, value: number) { this.dialog = dialog this.value = value } }
请参考demo: