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 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 280