ArkTs-自定义弹窗退出动画问题

问题描述

官方给出的增加自定义弹窗的动画的方法如下:

https://developer.huawei.com/consumer/cn/doc/harmonyos-faqs-V5/faqs-arkui-223-V5

1.在弹窗的布局上,通过.transition(…)设置布局的动画

2.通过一个变量代表visibility,改变布局的显示与否

点击“取消”按钮时,修改flag ->触发visibility变化 ->UI布局做动画,通过这个流程实现了dialog的入场/出场动画;同时,因为退出dialog时需要给退出动画流出时间,必须设置setTimeOut,等待动画时间后再关闭通过dialogController关闭弹窗。

如何在非点击按钮关闭弹窗的情况下(autoCancel下点击背景、back手势),也让弹窗能够做退出动画?

1.使用DialogStatus在外层Component中控制dialog的可见不可见

2.通过onWillDismiss监听弹窗背景的点击和back手势

实践方案

1.使用dialogController的方式来控制dialog的打开/关闭

2.dialogController创建时,通过onWillDismiss来拦截背景点击和back手势退出

3.在@Component下,维护一个DialogStatus变量,作为外层控制dialog显示与否的flag(启动时设置成true,关闭时设置成false)

4.在dialog布局下,使用DialogStatus控制dialog的布局显示

代码如下:

1.布局代码

@Component
export struct DemoView {
    ...
    dialogController: CustomDialogController|null = null;
    @State dialogStatus: DialogStatus = new DialogStatus(); // 在Component下维护flag,传入dialog,控制dialog显示变化
    ...
    
    aboutToAppear(): void {
        this.dialogController = new CustomDialogController({
            builder: DemoDialog({
                ...
                dialogStatus: this.dialogStatus // 此处传入dialog
            }),
            onWillDismiss: (dismissDialogAction: DismissDialogAction) => {
                // 点击系统返回按钮关闭对话框 || 点击弹窗背景关闭对话框
                if (dismissDialogAction.reason == DismissReason.PRESS_BACK ||
                    dismissDialogAction.reason == DismissReason.TOUCH_OUTSIDE) {
                    this.dialogStatus.isVisible = false;
                }
            },
            ...
        });

        ...
    }
    
    aboutToDisappear(): void {
        this.dialogController = null;
        ...
    }

    build() {
        .....
            .onClick(() => {
                        this.dialogStatus.isVisible = true; // 此处在调用open前一定要手动设置一次true,来回开关弹窗时弹窗的状态需要重置
                        this.dialogController?.open();
                    });
    }
}

2.弹窗代码

@CustomDialog
@Component
export struct DemoDialog {
    @ObjectLink @Watch('onDialogStatusChanged') dialogStatus: DialogStatus;
    ...
    dialogController: CustomDialogController = new CustomDialogController({'builder': ''});
    ...
    
    // dialog中通过监听status的变化来知晓是否要关闭弹窗
    onDialogStatusChanged() {
        if (!this.dialogStatus.isVisible) {
            setTimeout(() => {
                this.dialogController.close();
            }, animateDuration);
        }
    }
    
    build() {
        ...
        .visibility(this.dialogStatus.isVisible ? Visibility.Visible : Visibility.Hidden) // status用于控制visibility
        .transition(TransitionEffect.OPACITY.animation({duration: animateDuration}) // 添加入场/出场动画
            .combine(TransitionEffect.translate({y: 100})));
    }
}
posted @ 2025-01-04 14:16  jio-deng  阅读(82)  评论(0)    收藏  举报  来源