• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Custom Dialog Box (CustomDialog)
2
3A custom dialog box is a dialog box you customize by using APIs of the **CustomDialogController** class. You can set the style and content to your preference for a custom dialog box.
4
5> **NOTE**
6>
7> The APIs of this module are supported since API version 7. Updates will be marked with a superscript to indicate their earliest API version.
8
9
10## APIs
11
12CustomDialogController(value: CustomDialogControllerOptions)
13
14Defines a custom dialog box.
15
16> **NOTE**
17>
18> No parameters of the custom dialog box can be dynamically updated.
19
20**System capability**: SystemCapability.ArkUI.ArkUI.Full
21
22**Parameters**
23
24| Name| Type                                                        | Mandatory| Description                  |
25| ------ | ------------------------------------------------------------ | ---- | ---------------------- |
26| value  | [CustomDialogControllerOptions](#customdialogcontrolleroptions) | Yes  | Parameters of the custom dialog box.|
27
28## CustomDialogControllerOptions
29
30| Name                          | Type                                    | Mandatory  | Description                                    |
31| ----------------------------- | ---------------------------------------- | ---- | ---------------------------------------- |
32| builder                       | [CustomDialog](../../ui/arkts-common-components-custom-dialog.md) | Yes   | Builder of the custom dialog box content.                             |
33| cancel                        | () => void                  | No   | Callback invoked when the dialog box is closed after the Back key, the ESC key, or the mask is clicked.|
34| autoCancel                    | boolean                                  | No   | Whether to close the dialog box when the overlay is clicked. The value **true** means to close the dialog box when the overlay is clicked, and **false** means the opposite.<br>Default value: **true**|
35| alignment                     | [DialogAlignment](ts-methods-alert-dialog-box.md#dialogalignment) | No   | Alignment mode of the dialog box in the vertical direction.<br>Default value: **DialogAlignment.Default**|
36| offset                        | [Offset](ts-types.md#offset)             | No   | Offset of the dialog box relative to the alignment position.                  |
37| customStyle                   | boolean                                  | No   | Whether to use a custom style for the dialog box.<br>**false** (default): The dialog box automatically adapts its width to the grid system and its height to the child components; the maximum height is 90% of the container height; the rounded corner is 24 vp.<br>**true**: The dialog box automatically adapts its width to the child components; the rounded corner is 0; the background color is transparent.|
38| gridCount<sup>8+</sup>        | number                                   | No   | Number of [grid columns](../../ui/arkts-layout-development-grid-layout.md) occupied by the dialog box.<br>The default value is subject to the window size, and the maximum value is the maximum number of columns supported by the system. If this parameter is set to an invalid value, the default value is used.|
39| maskColor<sup>10+</sup>       | [ResourceColor](ts-types.md#resourcecolor) | No   | Custom mask color.<br>Default value: **0x33000000**             |
40| maskRect<sup>10+</sup>        | [Rectangle](ts-methods-alert-dialog-box.md#rectangle8) | No    | Mask area of the dialog box. Events outside the mask area are transparently transmitted, and events within the mask area are not.<br>Default value: **{ x: 0, y: 0, width: '100%', height: '100%' }**|
41| openAnimation<sup>10+</sup>   | [AnimateParam](../arkui-ts/ts-explicit-animation.md#animateparam) | No   | Parameters for defining the open animation of the dialog box.<br>**NOTE**<br>**iterations**: The default value is **1**, indicating that the animation is played once; any other value evaluates to the default value.<br>**playMode**: The default value is **PlayMode.Normal**; any other value evaluates to the default value.|
42| closeAnimation<sup>10+</sup>  | [AnimateParam](../arkui-ts/ts-explicit-animation.md#animateparam) | No   | Parameters for defining the close animation of the dialog box.<br>**NOTE**<br>**iterations**: The default value is **1**, indicating that the animation is played once; any other value evaluates to the default value.<br>**playMode**: The default value is **PlayMode.Normal**; any other value evaluates to the default value.<br>For page transition, you are advised to use the default close animation.                   |
43| showInSubWindow<sup>10+</sup> | boolean                                  | No   | Whether to show the dialog box in a sub-window when the dialog box needs to be displayed outside the main window.<br>Default value: **false**<br>**NOTE**<br>A dialog box whose **showInSubWindow** attribute is **true** cannot trigger the display of another dialog box whose **showInSubWindow** attribute is also **true**.|
44| backgroundColor<sup>10+</sup> | [ResourceColor](ts-types.md#resourcecolor)      | No  | Background color of the dialog box.<br>**NOTE**<br>If the content builder also has the background color set, the background color set here will be overridden by the background color of the content builder.|
45| cornerRadius<sup>10+</sup>    | [BorderRadiuses](ts-types.md#borderradiuses9) \| [Dimension](ts-types.md#dimension10) | No  | Radius of the rounded corners of the background.<br>You can set separate radiuses for the four rounded corners.<br>Default value: **{ topLeft: '24vp', topRight: '24vp', bottomLeft: '24vp', bottomRight: '24vp' }**<br>**NOTE**<br>This attribute must be used together with the [borderRadius](ts-universal-attributes-border.md#borderradius) attribute.|
46| isModal<sup>11+</sup> | boolean | No| Whether the dialog box is a modal. A modal dialog box has a mask applied, while a non-modal dialog box does not.<br>Default value: **true**|
47
48> **NOTE**
49>
50> - Pressing the Back or ESC key closes the dialog box.
51> - Use the custom dialog box to contain simple information only. Do not use it as a page. If the dialog box's height is too large, it may be partly blocked by the soft keyboard (if any), which is automatically raised when displayed.
52
53## CustomDialogController
54
55### Objects to Import
56
57```ts
58let dialogController : CustomDialogController = new CustomDialogController(CustomDialogControllerOptions)
59```
60> **NOTE**
61>
62> **CustomDialogController** is effective only when it is a member variable of the **@CustomDialog** and **@Component** decorated struct and is defined in the **@Component** decorated struct. For details, see the following example.
63
64### open
65open(): void
66
67
68Opens the content of the custom dialog box. This API can be called multiple times. If the dialog box displayed in a subwindow, no new subwindow is allowed.
69
70
71### close
72close(): void
73
74
75Closes the custom dialog box. If the dialog box is closed, this API does not take effect.
76
77## Example
78
79### Example 1
80
81```ts
82// xxx.ets
83@CustomDialog
84struct CustomDialogExampleTwo {
85  controllerTwo?: CustomDialogController
86  build() {
87    Column() {
88      Text('I'm the second dialog box.')
89        .fontSize(30)
90        .height(100)
91      Button ('Close Second Dialog Box')
92        .onClick(() => {
93          if (this.controllerTwo != undefined) {
94            this.controllerTwo.close()
95          }
96        })
97        .margin(20)
98    }
99  }
100}
101@CustomDialog
102struct CustomDialogExample {
103  @Link textValue: string
104  @Link inputValue: string
105  dialogControllerTwo: CustomDialogController | null = new CustomDialogController({
106    builder: CustomDialogExampleTwo(),
107    alignment: DialogAlignment.Bottom,
108    offset: { dx: 0, dy: -25 } })
109  controller?: CustomDialogController
110  // You can pass in multiple other controllers in the CustomDialog to open one or more other CustomDialogs in the CustomDialog. In this case, you must place the controller pointing to the self behind all controllers.
111  cancel: () => void = () => {
112  }
113  confirm: () => void = () => {
114  }
115
116  build() {
117    Column() {
118      Text('Change text').fontSize(20).margin({ top: 10, bottom: 10 })
119      TextInput({ placeholder: '', text: this.textValue }).height(60).width('90%')
120        .onChange((value: string) => {
121          this.textValue = value
122        })
123      Text('Are you sure you want to change text?').fontSize(16).margin({ bottom: 10 })
124      Flex({ justifyContent: FlexAlign.SpaceAround }) {
125        Button('No')
126          .onClick(() => {
127            if (this.controller != undefined) {
128              this.controller.close()
129              this.cancel()
130            }
131          }).backgroundColor(0xffffff).fontColor(Color.Black)
132        Button('Yes')
133          .onClick(() => {
134            if (this.controller != undefined) {
135              this.inputValue = this.textValue
136              this.controller.close()
137              this.confirm()
138            }
139          }).backgroundColor(0xffffff).fontColor(Color.Red)
140      }.margin({ bottom: 10 })
141
142      Button ('Open Second Dialog Box')
143        .onClick(() => {
144          if (this.dialogControllerTwo != null) {
145            this.dialogControllerTwo.open()
146          }
147        })
148        .margin(20)
149    }.borderRadius(10)
150    // When using the border or cornerRadius attribute, use it together with the borderRadius attribute.
151  }
152}
153@Entry
154@Component
155struct CustomDialogUser {
156  @State textValue: string = ''
157  @State inputValue: string = 'Click Me'
158  dialogController: CustomDialogController | null = new CustomDialogController({
159    builder: CustomDialogExample({
160      cancel: this.onCancel,
161      confirm: this.onAccept,
162      textValue: $textValue,
163      inputValue: $inputValue
164    }),
165    cancel: this.exitApp,
166    autoCancel: true,
167    alignment: DialogAlignment.Bottom,
168    offset: { dx: 0, dy: -20 },
169    gridCount: 4,
170    customStyle: false,
171    cornerRadius: 10,
172  })
173
174  // Set dialogController to null when the custom component is about to be destructed.
175  aboutToDisappear() {
176    this.dialogController = null // Set dialogController to null.
177  }
178
179  onCancel() {
180    console.info('Callback when the first button is clicked')
181  }
182
183  onAccept() {
184    console.info('Callback when the second button is clicked')
185  }
186
187  exitApp() {
188    console.info('Click the callback in the blank area')
189  }
190  build() {
191    Column() {
192      Button(this.inputValue)
193        .onClick(() => {
194          if (this.dialogController != null) {
195            this.dialogController.open()
196          }
197        }).backgroundColor(0x317aff)
198    }.width('100%').margin({ top: 5 })
199  }
200}
201```
202
203![en-us_image_custom](figures/en-us_image_custom.gif)
204
205### Example 2
206
207```ts
208// xxx.ets
209@CustomDialog
210struct CustomDialogExample {
211  controller?: CustomDialogController
212  cancel: () => void = () => {
213  }
214  confirm: () => void = () => {
215  }
216  build() {
217    Column() {
218      Text('Dialog box outside the main window')
219        .fontSize(30)
220        .height(100)
221      Button ('Close')
222        .onClick(() => {
223          if (this.controller != undefined) {
224            this.controller.close()
225          }
226        })
227        .margin(20)
228    }
229  }
230}
231@Entry
232@Component
233struct CustomDialogUser {
234  dialogController: CustomDialogController | null = new CustomDialogController({
235    builder: CustomDialogExample({
236      cancel: this.onCancel,
237      confirm: this.onAccept
238    }),
239    cancel: this.existApp,
240    autoCancel: true,
241    alignment: DialogAlignment.Center,
242    offset: { dx: 0, dy: -20 },
243    gridCount: 4,
244    showInSubWindow: true,
245    isModal: true,
246    customStyle: false,
247    cornerRadius: 10,
248  })
249  // Set dialogController to null when the custom component is about to be destroyed.
250  aboutToDisappear() {
251    this.dialogController = null // Set dialogController to null.
252  }
253
254  onCancel() {
255    console.info('Callback when the first button is clicked')
256  }
257
258  onAccept() {
259    console.info('Callback when the second button is clicked')
260  }
261
262  existApp() {
263    console.info('Click the callback in the blank area')
264  }
265
266  build() {
267    Column() {
268      Button('Click Me')
269        .onClick(() => {
270          if (this.dialogController != null) {
271            this.dialogController.open()
272          }
273        }).backgroundColor(0x317aff)
274    }.width('100%').margin({ top: 5 })
275  }
276}
277```
278
279![en-us_image_custom-showinsubwindow](figures/en-us_image_custom-showinsubwindow.jpg)
280