Skip to content

弹窗与对话框

ArkUI 提供多种弹窗组件,各有不同的使用场景和 API。


1. 弹窗组件分类

弹窗体系
├── Dialog(系统弹窗)
├── CustomDialogController(自定义弹窗)
├── Popup(弹出框)
├── ActionSheet(底部操作面板)
└── PromptActionSheet(底部提示面板)

2. Dialog — 系统弹窗

2.1 基本用法

typescript
@Entry
@Component
struct Index {
    private dialogController: DialogController = new DialogController({
        autoCancel: true,       // 点击外部是否关闭
        alignment: DialogAlignment.Center,  // 对齐方式
        offset: { dx: 0, dy: 0 }
    })

    build() {
        Column() {
            Button('打开系统弹窗')
                .onClick(() => {
                    this.dialogController.open(
                        // 内容
                        () => {
                            Text('确定要删除这条数据吗?')
                                .fontSize(18fp)
                        },
                        // 按钮列表
                        [
                            {
                                action: '取消',
                                actionChild: () => this.dialogController.close()
                            },
                            {
                                action: '删除',
                                actionChild: () => {
                                    // 执行删除逻辑
                                    this.dialogController.close()
                                }
                            }
                        ],
                        // 配置
                        { cancel: () => this.dialogController.close() }
                    )
                })
        }
    }
}

2.2 对齐方式

方式说明
DialogAlignment.Top顶部居中
DialogAlignment.Bottom底部居中
DialogAlignment.Center居中
DialogAlignment.Start左侧居中
DialogAlignment.End右侧居中

3. CustomDialogController — 自定义弹窗 ⭐

3.1 弹窗内容定义

typescript
@CustomDialog
struct ConfirmDialog {
    controller: CustomDialogController
    @State title: string = '提示'
    @State content: string = '确定操作吗?'

    build() {
        Column() {
            Text(this.title)
                .fontSize(20fp)
                .fontWeight(FontWeight.Bold)
                .margin({ bottom: 16 })
                .textAlign(TextAlign.Center)

            Divider().margin({ bottom: 16 })

            Text(this.content)
                .fontSize(16fp)
                .textAlign(TextAlign.Center)
                .margin({ bottom: 24 })

            Row() {
                Button('取消')
                    .width('48%')
                    .onClick(() => this.controller.close())
                Button('确定')
                    .width('48%')
                    .onClick(() => {
                        // 执行操作
                        this.controller.close()
                    })
            }
            .width('100%')
        }
        .width('80%')
        .padding(24)
        .borderRadius(12)
        .backgroundColor(Color.White)
    }
}

3.2 弹窗控制器配置

typescript
@Entry
@Component
struct Index {
    private dialogController = new CustomDialogController({
        builder: ConfirmDialog({
            controller: null as any,
            title: '删除确认',
            content: '删除后不可恢复,确定吗?'
        }),
        alignment: DialogAlignment.Center,
        offset: { dx: 0, dy: 0 },
        autoCancel: true,
        customPanelState: CustomPanelState.POPUP,  // POPUP/DRAG
        width: CustomPanelWidth.MATCH_PARENT,
        cornerType: CornerType.ALL,
        showCloseButton: false,
        autoCancelOutside: true
    })

    build() {
        Column() {
            Button('打开自定义弹窗')
                .onClick(() => {
                    this.dialogController.open()
                })
        }
    }
}

3.3 CustomPanelState

状态说明
CustomPanelState.POPUP弹窗模式(标准弹出)
CustomPanelState.DRAG可拖拽面板(从底部弹出)

4. Popup — 弹出框

4.1 基本用法

typescript
@Entry
@Component
struct Index {
    private controller: PopupController = new PopupController({
        alignment: PopupAlignment.Bottom,
        offset: { dx: 0, dy: 0 },
        popover: {
            contentColor: Color.White,
            shape: PopoverShape.CIRCLE,  // CIRCLE/ROUND_RECT
            cornerRadius: 8,
            width: 200,
            height: 150,
            margin: 10
        }
    })

    build() {
        Column() {
            // 触发按钮
            Button('弹出菜单')
                .onClick(() => {
                    this.controller.open(() => {
                        // 弹出框内容
                        Column() {
                            Text('选项1').onClick(() => this.controller.close())
                            Text('选项2').onClick(() => this.controller.close())
                            Text('选项3').onClick(() => this.controller.close())
                        }
                    })
                })

            // 定位标记
            this.controller.reference('popup')
        }
        .width('100%')
        .height('100%')
    }
}

4.2 弹出位置

位置
底部居中PopupAlignment.Bottom
顶部居中PopupAlignment.Top
左侧居中PopupAlignment.Start
右侧居中PopupAlignment.End

5. ActionSheet — 底部操作面板

5.1 基本用法

typescript
@Entry
@Component
struct Index {
    private actionSheetController = new ActionSheetController({
        items: ['拍照', '从相册选择', '取消'],
        cancelTitle: '取消',
        destructiveIndex: -1
    })

    build() {
        Column() {
            Button('打开底部菜单')
                .onClick(() => {
                    this.actionSheetController.open((index) => {
                        if (index === 0) {
                            console.log('拍照')
                        } else if (index === 1) {
                            console.log('相册')
                        }
                    })
                })
        }
    }
}

5.2 配置项

配置说明
items菜单项列表
cancelTitle取消按钮文字
destructiveIndex危险操作的索引(红色文字)
disabledIndex禁用的索引
showCancel是否显示取消按钮

6. 弹窗最佳实践

6.1 弹窗与组件通信

typescript
// 父组件传递回调
@Entry
@Component
struct Index {
    private dialogController = new CustomDialogController({
        builder: ConfirmDialog({
            controller: null as any,
            onConfirm: () => {
                // 确认回调
                console.log('用户确认了')
            }
        }),
        alignment: DialogAlignment.Center
    })

    build() {
        Column() {
            Button('确认弹窗')
                .onClick(() => this.dialogController.open())
        }
    }
}

// 弹窗内容
@CustomDialog
struct ConfirmDialog {
    controller: CustomDialogController
    onConfirm: () => void = () => {}

    build() {
        Column() {
            Button('确定')
                .onClick(() => {
                    this.onConfirm()  // 调用父组件回调
                    this.controller.close()
                })
        }
    }
}

6.2 弹窗生命周期管理

typescript
@Component
struct LifecycleAwareDialog {
    controller: CustomDialogController

    aboutToAppear() {
        console.log('弹窗显示')
        // 弹窗打开后的初始化
    }

    aboutToDisappear() {
        console.log('弹窗关闭')
        // 弹窗关闭后的清理
    }

    build() {
        // ...
    }
}

7. 面试高频考点

Q1: 鸿蒙有哪些弹窗组件?

回答:Dialog(系统弹窗)、CustomDialogController(自定义弹窗)、Popup(弹出框)、ActionSheet(底部操作面板)、PromptActionSheet(底部提示面板)。

Q2: CustomDialogController 的 customPanelState 有哪些?

回答:POPUP(标准弹窗)和 DRAG(可拖拽面板,从底部弹出)。

Q3: 弹窗关闭的时机和清理?

回答:在 aboutToDisappear 生命周期中清理弹窗相关资源,如定时器、监听器等。


🐱 小猫提示:弹窗部分记住 "CustomDialogController 最灵活、ActionSheet 最便捷、Dialog 最标准"。面试中重点说 CustomDialog 的使用。