# 9.5:自定义对话框(PromptAction)

除了使用 CustomDialogController 实现自定义弹窗外,ArkUI 开发框架还提供了 PromptAction 对象实现弹框功能,本节笔者简单介绍一下 PromptAction 的使用。

# 9.5.1:PromptAction简介

PromptAction 需要从当前 UIContext 提供的 getPromptAction() 方法获取到,然后调用其 openCustomDialog()closeCustomDialog() 方法显示和隐藏自定义对话框。

PromptAction 定义如下:

export class PromptAction {

  openCustomDialog<T extends Object>(dialogContent: ComponentContent<T>, options?: promptAction.BaseDialogOptions): Promise<void>;

  closeCustomDialog<T extends Object>(dialogContent: ComponentContent<T>): Promise<void>;
}
1
2
3
4
5
6
  • openCustomDialog: 接收一个自定义的 ComponentContent 对象和对话框的配置项。
  • closeCustomDialog: 关闭一个自定义的 ComponentContent 对象。

# 9.5.2:创建ComponentContent

PromptActionopenCustomDialog() 方法接收一个 ComponentContent 对象,该对象定义如下:

export class ComponentContent<T extends Object> extends Content {
    constructor(uiContext: UIContext, builder: WrappedBuilder<[]>);
    constructor(uiContext: UIContext, builder: WrappedBuilder<[T]>, args: T);
    constructor(uiContext: UIContext, builder: WrappedBuilder<[T]>, args: T, options: BuildOptions);
}
1
2
3
4
5

该对象提供了三种创建方式,创建时需要传递一个 UIContext 和使用 wrapBuilder() 包装的 @Builder 对象,还可以给 @Builder 对象传递参数,创建 ComponentContent 实例简单样例如下所示:

import { ComponentContent, promptAction } from '@kit.ArkUI';
import { HashMap } from '@kit.ArkTS';

// 全局缓存集合
let globalDialogMap: HashMap<string, ComponentContent<string>> = new HashMap<string, ComponentContent<string>>()

// 自定义弹窗布局
@Builder function customComponentBuilder(dialogId: string) {
  Stack() {
    Column() {
      Text('电池电量不足')
        .fontSize(20)
        .margin({top: 15})
      Text('还剩20%电量')
        .fontSize(16)
        .margin({top: 3})
      Text()
        .size({width: "100%", height: "2px"})
        .backgroundColor("#bebbc1")
        .margin({top: 15})
      Row() {
        Text("关闭")
          .height("100%")
          .layoutWeight(1)
          .textAlign(TextAlign.Center)
          .fontSize(18)
          .fontColor("#317ef5")
          .onClick(() => {
          })
        Text()
          .size({width: "2px", height: "100%"})
          .backgroundColor("#bebbc1")
        Text("低电量模式")
          .textAlign(TextAlign.Center)
          .fontSize(18)
          .fontColor("#317ef5")
          .height("100%")
          .layoutWeight(1)
          .onClick(() => {
          })
      }
      .height(45)
      .width('100%')
    }
    .backgroundColor("#e6ffffff")
    .borderRadius(20)
  }
  .padding({left: 40, right: 40})
  .width("100%")
}

@Entry @ComponentV2 struct Page_ComponentContent {

  private customComponent: ComponentContent<string> | undefined = undefined // 声明ComponentContent,它接收一个string参数


  private initComponentContent() {
    // 定义一个表示当前对话框的id
    let dialogId = "10086"
    // 初始化ComponentContent,把dialogId传递进去
    this.customComponent = new ComponentContent(this.getUIContext(), wrapBuilder(customComponentBuilder), dialogId);
    // 缓存customComponent
    globalDialogMap.set(dialogId, this.customComponent)
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65

样例中定义了一个全局 globalDialogMap 来缓存创建的 ComponentContent,然后定义了 customComponentBuilder 来代表对话框的布局,最后在 initComponentContent() 创建该对话框。

# 9.5.3:显示ComponentContent

创建完 ComponentContent 后,接着是调用 PromptActionopenCustomDialog() 方法显示自定义对话框的内容,样例如下所示:

@Entry @ComponentV2 struct Page_07_loadmore {

  private customComponent: ComponentContent<string> | undefined = undefined

  // 显示自定义弹窗
  private showComponentContent() {
    let _promptAction = this.getUIContext().getPromptAction()
    _promptAction.openCustomDialog(this.customComponent)
  }
}
1
2
3
4
5
6
7
8
9
10

# 9.5.4:隐藏ComponentContent

当调用 PromptActionopenCustomDialog() 方法显示自定义对话框后,如果要隐藏对话框,这调用 PromptActionopenCustomDialog() 方法即可,简单样例如下所示:

@Entry @ComponentV2 struct Page_07_loadmore {

  private customComponent: ComponentContent<string> | undefined = undefined

  // 隐藏自定义弹窗
  private dismissComponentContent() {
    let _promptAction = this.getUIContext().getPromptAction()
    _promptAction.closeCustomDialog(this.customComponent)
  }
}
1
2
3
4
5
6
7
8
9
10

# 9.5.5:完整样例

使用 ComponentContent 方式显示和隐藏自定义对话框完整样例如下所示:

import { ComponentContent } from '@kit.ArkUI';
import { HashMap } from '@kit.ArkTS';

class ComponentWrapper {
  readonly context: UIContext;
  readonly component: ComponentContent<string>;

  constructor(context: UIContext, component: ComponentContent<string>) {
    this.context = context;
    this.component = component;
  }
}

let globalDialogMap: HashMap<string, ComponentWrapper> = new HashMap<string, ComponentWrapper>()

@Builder function customComponentBuilder(dialogId: string) {
  Stack() {
    Column() {
      Text('电池电量不足')
        .fontSize(20)
        .margin({top: 15})
      Text('还剩20%电量')
        .fontSize(16)
        .margin({top: 3})
      Text()
        .size({width: "100%", height: "2px"})
        .backgroundColor("#bebbc1")
        .margin({top: 15})
      Row() {
        Text("关闭")
          .height("100%")
          .layoutWeight(1)
          .textAlign(TextAlign.Center)
          .fontSize(18)
          .fontColor("#317ef5")
          .onClick(() => { // 点击关闭弹出
            let wrapper = globalDialogMap.get(dialogId)
            if (wrapper) {
              wrapper.context.getPromptAction().closeCustomDialog(wrapper.component)
            }
          })
        Text()
          .size({width: "2px", height: "100%"})
          .backgroundColor("#bebbc1")
        Text("低电量模式")
          .textAlign(TextAlign.Center)
          .fontSize(18)
          .fontColor("#317ef5")
          .height("100%")
          .layoutWeight(1)
          .onClick(() => { // 点击关闭弹窗
            let wrapper = globalDialogMap.get(dialogId)
            if (wrapper) {
              wrapper.context.getPromptAction().closeCustomDialog(wrapper.component)
            }
          })
      }
      .height(45)
      .width('100%')
    }
    .backgroundColor("#e6ffffff")
    .borderRadius(20)
  }
  .padding({left: 40, right: 40})
  .width("100%")
}

@Entry @ComponentV2 struct Page_07_loadmore {

  build() {
    Row({space: 15}) {
      Button("创建Dialog")
        .onClick(() => {
          this.initComponentContent()
        })

      Button("弹出Dialog")
        .onClick(() => {
          this.showComponentContent();
        })

      Button("隐藏Dialog")
        .onClick(() => {
          this.dismissComponentContent();
        })
    }
    .width("100%")
    .width('100%')
  }

  private initComponentContent() {
    let dialogId = "10086"
    let context = this.getUIContext();
    let customComponent = new ComponentContent(context, wrapBuilder(customComponentBuilder), dialogId);
    globalDialogMap.set(dialogId, new ComponentWrapper(context, customComponent))
  }

  private showComponentContent() {
    let dialogId = "10086"
    let wrapper = globalDialogMap.get(dialogId)
    if (wrapper) {
      wrapper.context.getPromptAction().openCustomDialog(wrapper.component)
    }
  }

  private dismissComponentContent() {
    let dialogId = "10086"
    let wrapper = globalDialogMap.get(dialogId)
    if (wrapper) {
      wrapper.context.getPromptAction().closeCustomDialog(wrapper.component)
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113

样例运行结果如下图所示:

9_5_5_1
请作者喝杯咖啡

津公网安备 12011402001367号

津ICP备2020008934号-2

中央网信办互联网违法和不良信息举报中心

天津市互联网违法和不良信息举报中心