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 12constructor(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**Atomic service API**: This API can be used in atomic services since API version 11. 21 22**System capability**: SystemCapability.ArkUI.ArkUI.Full 23 24**Parameters** 25 26| Name| Type | Mandatory| Description | 27| ------ | ------------------------------------------------------------ | ---- | ---------------------- | 28| value | [CustomDialogControllerOptions](#customdialogcontrolleroptions) | Yes | Parameters of the custom dialog box.| 29 30## CustomDialogControllerOptions 31 32**System capability**: SystemCapability.ArkUI.ArkUI.Full 33 34| Name | Type | Mandatory | Description | 35| ----------------------------- | ---------------------------------------- | ---- | ---------------------------------------- | 36| builder | [CustomDialog](../../../ui/arkts-common-components-custom-dialog.md) | Yes | Builder of the custom dialog box content.<br>**NOTE**<br>If the builder uses a callback as the input parameter, as in **build: custombuilder({ callback: ()=> {...}})**, pay attention to the binding of **this**.<br>To listen for data changes in the builder, use the @Link decorator; other decorators, such as @Prop and @ObjectLink, do not apply.<br>**Atomic service API**: This API can be used in atomic services since API version 11.| 37| cancel | () => void | No | Callback invoked when the dialog box is closed after the Back button or mask is touched or the Esc key is pressed.<br>**Atomic service API**: This API can be used in atomic services since API version 11.| 38| autoCancel | boolean | No | Whether to close the dialog box when the mask is touched. The value **true** means to close the dialog box when the mask is touched, and **false** means the opposite.<br>Default value: **true**<br>**Atomic service API**: This API can be used in atomic services since API version 11.| 39| 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**<br>**Atomic service API**: This API can be used in atomic services since API version 11.| 40| offset | [Offset](ts-types.md#offset) | No | Offset of the dialog box relative to the alignment position.<br>Default value: **{dx: 0, dy: 0}**<br>**Atomic service API**: This API can be used in atomic services since API version 11.| 41| customStyle | boolean | No | Whether to use a custom style for the dialog box.<br>When this parameter is set to **false** (default value):<br>1. The rounded corner radius is 32 vp.<br>2. If the width and height of the dialog box are not set, the dialog box automatically adapts its width to the grid system and its height to the child components.<br>3. The set width of the dialog box cannot exceed the maximum width in the default style (100% width for a custom node), and the set height cannot exceed the maximum height (100% height for a custom node).<br>When this parameter is set to **true**:<br>1. The corner radius is 0, and the background color is transparent.<br>2. The width, height, border width, border style, border color, and shadow width cannot be set for the dialog box.<br>**Atomic service API**: This API can be used in atomic services since API version 11.| 42| 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.<br>**Atomic service API**: This API can be used in atomic services since API version 11.| 43| maskColor<sup>10+</sup> | [ResourceColor](ts-types.md#resourcecolor) | No | Custom mask color.<br>Default value: **0x33000000**<br>**Atomic service API**: This API can be used in atomic services since API version 11. | 44| 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%' }**<br>**NOTE**<br>**maskRect** does not take effect when **showInSubWindow** is set to **true**.<br>**Atomic service API**: This API can be used in atomic services since API version 11.| 45| openAnimation<sup>10+</sup> | [AnimateParam](ts-explicit-animation.md#animateparam) | No | Parameters for defining the open animation of the dialog box.<br>**NOTE**<br>**tempo**: The default value is **1**; a value less than or equal to 0 is handled as the default value.<br>**iterations**: The default value is **1**, indicating that the animation is played once; any other value is handled as the default value.<br>**playMode**: The default value is **PlayMode.Normal**; any other value is handled as the default value.<br>**Atomic service API**: This API can be used in atomic services since API version 11.| 46| closeAnimation<sup>10+</sup> | [AnimateParam](ts-explicit-animation.md#animateparam) | No | Parameters for defining the close animation of the dialog box.<br>**NOTE**<br>**tempo**: The default value is **1**; a value less than or equal to 0 is handled as the default value.<br>**iterations**: The default value is **1**, indicating that the animation is played once; any other value is handled as the default value.<br>**playMode**: The default value is **PlayMode.Normal**; any other value is handled as the default value.<br>For page transition, you are advised to use the default close animation.<br>**Atomic service API**: This API can be used in atomic services since API version 11.| 47| 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**. Avoid using the **CalendarPicker**, **CalendarPickerDialog**, **DatePickerDialog**, **TextPickerDialog**, and **TimePickerDialog** components in the dialog box where **showInSubWindow** is set to **true**, as the dialog box may affect the behavior of these components.<br>**Atomic service API**: This API can be used in atomic services since API version 11.| 48| backgroundColor<sup>10+</sup> | [ResourceColor](ts-types.md#resourcecolor) | No | Background color of the dialog box.<br>Default value: **Color.Transparent**<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.<br>When **backgroundColor** is set to a non-transparent color, **backgroundBlurStyle** must be set to **BlurStyle.NONE**; otherwise, the color display may not meet the expected effect.<br>**Atomic service API**: This API can be used in atomic services since API version 11.| 49| cornerRadius<sup>10+</sup> | [Dimension](ts-types.md#dimension10) \| [BorderRadiuses](ts-types.md#borderradiuses9) | No | Radius of the rounded corners of the background.<br>You can set separate radiuses for the four rounded corners.<br>Default value: **{ topLeft: '32vp', topRight: '32vp', bottomLeft: '32vp', bottomRight: '32vp' }**<br>**NOTE**<br>This attribute must be used together with the [borderRadius](ts-universal-attributes-border.md#borderradius) attribute.<br>**Atomic service API**: This API can be used in atomic services since API version 11.| 50| 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**<br>**Atomic service API**: This API can be used in atomic services since API version 12.| 51| onWillDismiss<sup>12+</sup> | Callback<[DismissDialogAction](#dismissdialogaction12)> | No| Callback for interactive closure of the dialog box.<br>**NOTE**<br>1. If this callback is registered, the dialog box will not be closed immediately after the user touches the mask or the Back button, presses the Esc key, or swipes left or right on the screen. The **reason** parameter in the callback is used to determine whether the dialog box can be closed. The reason returned by the component does not support the value **CLOSE_BUTTON**.<br>2. In the **onWillDismiss** callback, another **onWillDismiss** callback is not allowed.<br>**Atomic service API**: This API can be used in atomic services since API version 12.| 52| borderWidth<sup>12+</sup> | [Dimension](ts-types.md#dimension10) \| [EdgeWidths](ts-types.md#edgewidths9) | No| Border width of the dialog box.<br>You can set the width for all four sides or set separate widths for individual sides.<br>Default value: **0**<br> When set to a percentage, the value defines the border width as a percentage of the parent dialog box's width.<br>If the left and right borders are greater than its width, or the top and bottom borders are greater than its height, the dialog box may not display as expected.<br>**Atomic service API**: This API can be used in atomic services since API version 12.| 53| borderColor<sup>12+</sup> | [ResourceColor](ts-types.md#resourcecolor) \| [EdgeColors](ts-types.md#edgecolors9) | No| Border color of the dialog box.<br>Default value: **Color.Black**<br>**borderColor** must be used with **borderWidth** in pairs.<br>**Atomic service API**: This API can be used in atomic services since API version 12.| 54| borderStyle<sup>12+</sup> | [BorderStyle](ts-appendix-enums.md#borderstyle) \| [EdgeStyles](ts-types.md#edgestyles9) | No| Border style of the dialog box.<br>Default value: **BorderStyle.Solid**<br>**borderStyle** must be used with **borderWidth** in pairs.<br>**Atomic service API**: This API can be used in atomic services since API version 12.| 55| width<sup>12+</sup> | [Dimension](ts-types.md#dimension10) | No | Width of the dialog box.<br>**NOTE**<br>- Default maximum width of the dialog box: 400 vp<br>- When this parameter is set to a percentage, the reference width of the dialog box is the width of the window where the dialog box is located. You can decrease or increase the width as needed.<br>**Atomic service API**: This API can be used in atomic services since API version 12.| 56| height<sup>12+</sup> | [Dimension](ts-types.md#dimension10) | No| Height of the dialog box.<br>**NOTE**<br>- Default maximum height of the dialog box: 0.9 x (Window height – Safe area)<br>- When this parameter is set to a percentage, the reference height of the dialog box is the height of the window where the dialog box is located minus the safe area. You can decrease or increase the height as needed.<br>**Atomic service API**: This API can be used in atomic services since API version 12.| 57| shadow<sup>12+</sup> | [ShadowOptions](ts-universal-attributes-image-effect.md#shadowoptions) \| [ShadowStyle](ts-universal-attributes-image-effect.md#shadowstyle10) | No| Shadow of the dialog box.<br> Default value on 2-in-1 devices: **ShadowStyle.OUTER_FLOATING_MD** when the dialog box is focused and **ShadowStyle.OUTER_FLOATING_SM** otherwise<br>**Atomic service API**: This API can be used in atomic services since API version 12.| 58| backgroundBlurStyle<sup>12+</sup> | [BlurStyle](ts-universal-attributes-background.md#blurstyle9) | No | Background blur style of the dialog box.<br>Default value: **BlurStyle.COMPONENT_ULTRA_THICK**<br>**NOTE**<br>Setting this parameter to **BlurStyle.NONE** disables the background blur. When **backgroundBlurStyle** is set to a value other than **NONE**, do not set **backgroundColor**. If you do, the color display may not produce the expected visual effect.<br>**Atomic service API**: This API can be used in atomic services since API version 12.| 59| keyboardAvoidMode<sup>12+</sup> | [KeyboardAvoidMode](ts-types.md#keyboardavoidmode12) | No| How the dialog box avoids the soft keyboard when it is brought up.<br>Default value: **KeyboardAvoidMode.DEFAULT**<br>**Atomic service API**: This API can be used in atomic services since API version 12.| 60| enableHoverMode<sup>14+</sup> | boolean | No | Whether to enable the hover state.<br>Default value: **false**, meaning not to enable the hover state.<br>**Atomic service API**: This API can be used in atomic services since API version 14.| 61| hoverModeArea<sup>14+</sup> | [HoverModeAreaType](ts-appendix-enums.md#hovermodeareatype14) | No | Display area of the dialog box in the hover state.<br>Default value: **HoverModeAreaType.BOTTOM_SCREEN**<br>**Atomic service API**: This API can be used in atomic services since API version 14.| 62| keyboardAvoidDistance<sup>15+</sup> | [LengthMetrics](../js-apis-arkui-graphics.md#lengthmetrics12) | No | Minimum distance between the dialog box and the keyboard after keyboard avoidance is applied.<br>**NOTE**<br>- Default value: **16vp**<br>- Default unit: vp<br>- This parameter takes effect only when **keyboardAvoidMode** is set to **DEFAULT**.<br>**Atomic service API**: This API can be used in atomic services since API version 15.| 63| levelMode<sup>15+</sup> | [LevelMode](../js-apis-promptAction.md#levelmode15) | No | Display level of the dialog box.<br>**NOTE**<br>- Default value: **LevelMode.OVERLAY.**<br>- This parameter takes effect only when **showInSubWindow** is set to **false**.<br>**Atomic service API**: This API can be used in atomic services since API version 15.| 64| levelUniqueId<sup>15+</sup> | number | No | [Unique ID](../js-apis-arkui-frameNode.md#getuniqueid12) of the node under the display level for the page-level dialog box.<br>**NOTE**<br>- This parameter takes effect only when **levelMode** is set to **LevelMode.EMBEDDED**.<br>**Atomic service API**: This API can be used in atomic services since API version 15.| 65| immersiveMode<sup>15+</sup> | [ImmersiveMode](../js-apis-promptAction.md#immersivemode15) | No | Overlay effect for the page-level dialog box.<br>**NOTE**<br>- Default value: **ImmersiveMode.DEFAULT**<br>- This parameter takes effect only when **levelMode** is set to **LevelMode.EMBEDDED**.<br>**Atomic service API**: This API can be used in atomic services since API version 15.| 66 67> **NOTE** 68> 69> - Pressing the Back or ESC key closes the dialog box. 70> - If the dialog box reaches its maximum allowable height on the screen when avoiding the soft keyboard, it reduces its height to fit. 71> It should be noted that this height adjustment is applied to the outermost container. If a child component within this container has been assigned a larger fixed height, since the container does not clip its content by default, parts of the dialog box may still be displayed off-screen. 72> - Use the custom dialog box to contain simple alert messages only. Do not use it as a page. When the dialog box avoids the soft keyboard, there is a 16 vp safe spacing between the two. 73> 74> - Currently, dialog boxes in ArkUI do not close automatically when you switch pages unless you manually call **close**. To enable a dialog box to be covered during page navigation, consider using the **Navigation** component. For details, see the [page display mode: dialog mode](../../../ui/arkts-navigation-navigation.md#page-display-mode). 75 76## DismissDialogAction<sup>12+</sup> 77 78Provides information about the action to dismiss the dialog box. 79 80**Atomic service API**: This API can be used in atomic services since API version 12. 81 82**System capability**: SystemCapability.ArkUI.ArkUI.Full 83 84### Properties 85 86| Name | Type | Readable| Writable| Description | 87| ------- | ------------------------------------------------------------ | ---- | ---- | ------------------------------------------------------------ | 88| dismiss | Callback<void> | No | No | Callback for dismissing the dialog box. This API is called only when the dialog box needs to be exited.| 89| reason | [DismissReason](../js-apis-promptAction.md#dismissreason12) | No | No | Reason why the dialog box cannot be dismissed. You must specify whether to close the dialog box for each of the listed actions.| 90 91## CustomDialogController 92 93**Atomic service API**: This API can be used in atomic services since API version 11. 94 95### Objects to Import 96 97```ts 98dialogController : CustomDialogController | null = new CustomDialogController(CustomDialogControllerOptions) 99``` 100> **NOTE** 101> 102> **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. 103 104### constructor 105 106constructor(value: CustomDialogControllerOptions) 107 108Constructor for a custom dialog box. 109 110**Atomic service API**: This API can be used in atomic services since API version 11. 111 112**System capability**: SystemCapability.ArkUI.ArkUI.Full 113 114**Parameters** 115 116| Name| Type | Mandatory| Description | 117| ------ | ------------------------------------------------------------ | ---- | ---------------------- | 118| value | [CustomDialogControllerOptions](#customdialogcontrolleroptions) | Yes | Parameters of the custom dialog box.| 119 120### open 121 122open() 123 124Opens the content of the custom dialog box. This API can be called multiple times. If the dialog box is displayed in a subwindow, no new subwindow is allowed. 125 126**Atomic service API**: This API can be used in atomic services since API version 11. 127 128**System capability**: SystemCapability.ArkUI.ArkUI.Full 129 130 131### close 132 133close() 134 135**Atomic service API**: This API can be used in atomic services since API version 11. 136 137**System capability**: SystemCapability.ArkUI.ArkUI.Full 138 139 140Closes the custom dialog box. If the dialog box is closed, this API does not take effect. 141 142## Example 143 144### Example 1: Opening Nested Dialog Boxes 145 146This example demonstrates how to open one or more custom dialog boxes within another custom dialog box. 147 148```ts 149// xxx.ets 150@CustomDialog 151struct CustomDialogExampleTwo { 152 controllerTwo?: CustomDialogController 153 build() { 154 Column() { 155 Text('I'm the second dialog box') 156 .fontSize(30) 157 .height(100) 158 Button('Close Second Dialog Box') 159 .onClick(() => { 160 if (this.controllerTwo != undefined) { 161 this.controllerTwo.close() 162 } 163 }) 164 .margin(20) 165 } 166 } 167} 168@CustomDialog 169@Component 170struct CustomDialogExample { 171 @Link textValue: string 172 @Link inputValue: string 173 dialogControllerTwo: CustomDialogController | null = new CustomDialogController({ 174 builder: CustomDialogExampleTwo(), 175 alignment: DialogAlignment.Bottom, 176 onWillDismiss:(dismissDialogAction: DismissDialogAction)=> { 177 console.info("reason=" + JSON.stringify(dismissDialogAction.reason)) 178 console.log("dialog onWillDismiss") 179 if (dismissDialogAction.reason == DismissReason.PRESS_BACK) { 180 dismissDialogAction.dismiss() 181 } 182 if (dismissDialogAction.reason == DismissReason.TOUCH_OUTSIDE) { 183 dismissDialogAction.dismiss() 184 } 185 }, 186 offset: { dx: 0, dy: -25 } }) 187 controller?: CustomDialogController 188 // 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. 189 cancel: () => void = () => { 190 } 191 confirm: () => void = () => { 192 } 193 194 build() { 195 Column() { 196 Text('Change text').fontSize(20).margin({ top: 10, bottom: 10 }) 197 TextInput({ placeholder: '', text: this.textValue }).height(60).width('90%') 198 .onChange((value: string) => { 199 this.textValue = value 200 }) 201 Text('Are you sure you want to change the text?').fontSize(16).margin({ bottom: 10 }) 202 Flex({ justifyContent: FlexAlign.SpaceAround }) { 203 Button('No') 204 .onClick(() => { 205 if (this.controller != undefined) { 206 this.controller.close() 207 this.cancel() 208 } 209 }).backgroundColor(0xffffff).fontColor(Color.Black) 210 Button('OK') 211 .onClick(() => { 212 if (this.controller != undefined) { 213 this.inputValue = this.textValue 214 this.controller.close() 215 this.confirm() 216 } 217 }).backgroundColor(0xffffff).fontColor(Color.Red) 218 }.margin({ bottom: 10 }) 219 220 Button('Open Second Dialog Box') 221 .onClick(() => { 222 if (this.dialogControllerTwo != null) { 223 this.dialogControllerTwo.open() 224 } 225 }) 226 .margin(20) 227 }.borderRadius(10) 228 // When using the border or cornerRadius attribute, use it together with the borderRadius attribute. 229 } 230} 231@Entry 232@Component 233struct CustomDialogUser { 234 @State textValue: string = '' 235 @State inputValue: string = 'click me' 236 dialogController: CustomDialogController | null = new CustomDialogController({ 237 builder: CustomDialogExample({ 238 cancel: ()=> { this.onCancel() }, 239 confirm: ()=> { this.onAccept() }, 240 textValue: $textValue, 241 inputValue: $inputValue 242 }), 243 cancel: this.exitApp, 244 autoCancel: true, 245 onWillDismiss:(dismissDialogAction: DismissDialogAction)=> { 246 console.info("reason=" + JSON.stringify(dismissDialogAction.reason)) 247 console.log("dialog onWillDismiss") 248 if (dismissDialogAction.reason == DismissReason.PRESS_BACK) { 249 dismissDialogAction.dismiss() 250 } 251 if (dismissDialogAction.reason == DismissReason.TOUCH_OUTSIDE) { 252 dismissDialogAction.dismiss() 253 } 254 }, 255 alignment: DialogAlignment.Bottom, 256 offset: { dx: 0, dy: -20 }, 257 gridCount: 4, 258 customStyle: false, 259 cornerRadius: 10, 260 }) 261 262 // Set dialogController to null when the custom component is about to be destroyed. 263 aboutToDisappear() { 264 this.dialogController = null // Set dialogController to null. 265 } 266 267 onCancel() { 268 console.info('Callback when the first button is clicked') 269 } 270 271 onAccept() { 272 console.info('Callback when the second button is clicked') 273 } 274 275 exitApp() { 276 console.info('Click the callback in the blank area') 277 } 278 build() { 279 Column() { 280 Button(this.inputValue) 281 .onClick(() => { 282 if (this.dialogController != null) { 283 this.dialogController.open() 284 } 285 }).backgroundColor(0x317aff) 286 }.width('100%').margin({ top: 5 }) 287 } 288} 289``` 290 291 292 293### Example 2: Opening a Dialog Box Outside the Main Window 294 295This example demonstrates how to configure a dialog box to display outside the main window by setting **showInSubWindow** to **true**. 296 297```ts 298// xxx.ets 299@CustomDialog 300struct CustomDialogExample { 301 controller?: CustomDialogController 302 cancel: () => void = () => { 303 } 304 confirm: () => void = () => { 305 } 306 build() { 307 Column() { 308 Text('Dialog box outside the main window') 309 .fontSize(30) 310 .height(100) 311 Button('Close') 312 .onClick(() => { 313 if (this.controller != undefined) { 314 this.controller.close() 315 } 316 }) 317 .margin(20) 318 } 319 } 320} 321@Entry 322@Component 323struct CustomDialogUser { 324 dialogController: CustomDialogController | null = new CustomDialogController({ 325 builder: CustomDialogExample({ 326 cancel: ()=> { this.onCancel() }, 327 confirm: ()=> { this.onAccept() } 328 }), 329 cancel: this.existApp, 330 autoCancel: true, 331 onWillDismiss:(dismissDialogAction: DismissDialogAction)=> { 332 console.info("reason=" + JSON.stringify(dismissDialogAction.reason)) 333 console.log("dialog onWillDismiss") 334 if (dismissDialogAction.reason == DismissReason.PRESS_BACK) { 335 dismissDialogAction.dismiss() 336 } 337 if (dismissDialogAction.reason == DismissReason.TOUCH_OUTSIDE) { 338 dismissDialogAction.dismiss() 339 } 340 }, 341 alignment: DialogAlignment.Center, 342 offset: { dx: 0, dy: -20 }, 343 gridCount: 4, 344 showInSubWindow: true, 345 isModal: true, 346 customStyle: false, 347 cornerRadius: 10, 348 }) 349 // Set dialogController to null when the custom component is about to be destroyed. 350 aboutToDisappear() { 351 this.dialogController = null // Set dialogController to null. 352 } 353 354 onCancel() { 355 console.info('Callback when the first button is clicked') 356 } 357 358 onAccept() { 359 console.info('Callback when the second button is clicked') 360 } 361 362 existApp() { 363 console.info('Click the callback in the blank area') 364 } 365 366 build() { 367 Column() { 368 Button('Click Me') 369 .onClick(() => { 370 if (this.dialogController != null) { 371 this.dialogController.open() 372 } 373 }).backgroundColor(0x317aff) 374 }.width('100%').margin({ top: 5 }) 375 } 376} 377``` 378 379 380 381### Example 3: Setting the Dialog Box Style 382This example demonstrates how to set styles of a custom dialog box, including the width, height, background color, and shadow. 383```ts 384// xxx.ets 385@CustomDialog 386struct CustomDialogExample { 387 controller?: CustomDialogController 388 cancel: () => void = () => { 389 } 390 confirm: () => void = () => { 391 } 392 build() { 393 Column() { 394 Text('This is a custom dialog box') 395 .fontSize(30) 396 .height(100) 397 Button('Close') 398 .onClick(() => { 399 if (this.controller != undefined) { 400 this.controller.close() 401 } 402 }) 403 .margin(20) 404 } 405 } 406} 407@Entry 408@Component 409struct CustomDialogUser { 410 dialogController: CustomDialogController | null = new CustomDialogController({ 411 builder: CustomDialogExample({ 412 cancel: ()=> { this.onCancel() }, 413 confirm: ()=> { this.onAccept() } 414 }), 415 cancel: this.existApp, 416 autoCancel: true, 417 onWillDismiss:(dismissDialogAction: DismissDialogAction)=> { 418 console.info("reason=" + JSON.stringify(dismissDialogAction.reason)) 419 console.log("dialog onWillDismiss") 420 if (dismissDialogAction.reason == DismissReason.PRESS_BACK) { 421 dismissDialogAction.dismiss() 422 } 423 if (dismissDialogAction.reason == DismissReason.TOUCH_OUTSIDE) { 424 dismissDialogAction.dismiss() 425 } 426 }, 427 alignment: DialogAlignment.Center, 428 offset: { dx: 0, dy: -20 }, 429 customStyle: false, 430 cornerRadius: 20, 431 width: 300, 432 height: 200, 433 borderWidth: 1, 434 borderStyle: BorderStyle.Dashed,// borderStyle must be used with borderWidth in pairs. 435 borderColor: Color.Blue,// borderColor must be used with borderWidth in pairs. 436 backgroundColor: Color.White, 437 shadow: ({ radius: 20, color: Color.Grey, offsetX: 50, offsetY: 0}), 438 }) 439 // Set dialogController to null when the custom component is about to be destroyed. 440 aboutToDisappear() { 441 this.dialogController = null // Set dialogController to null. 442 } 443 444 onCancel() { 445 console.info('Callback when the first button is clicked') 446 } 447 448 onAccept() { 449 console.info('Callback when the second button is clicked') 450 } 451 452 existApp() { 453 console.info('Click the callback in the blank area') 454 } 455 456 build() { 457 Column() { 458 Button('Click Me') 459 .onClick(() => { 460 if (this.dialogController != null) { 461 this.dialogController.open() 462 } 463 }).backgroundColor(0x317aff) 464 }.width('100%').margin({ top: 5 }) 465 } 466} 467``` 468 469 470 471### Example 4: Configuring a Dialog Box in the Hover State 472 473This example demonstrates how to set the layout area of a dialog box in the hover state on a foldable device. 474 475```ts 476@CustomDialog 477@Component 478struct CustomDialogExample { 479 @Link textValue: string; 480 @Link inputValue: string; 481 controller?: CustomDialogController; 482 483 build() { 484 Column() { 485 Text('Change text').fontSize(20).margin({ top: 10, bottom: 10 }) 486 TextInput({ placeholder: '', text: this.textValue }).height(60).width('90%') 487 .onChange((value: string) => { 488 this.textValue = value; 489 }) 490 Text('Are you sure you want to change the text?').fontSize(16).margin({ bottom: 10 }) 491 Flex({ justifyContent: FlexAlign.SpaceAround }) { 492 Button('No') 493 .onClick(() => { 494 if (this.controller != undefined) { 495 this.controller.close(); 496 } 497 }).backgroundColor(0xffffff).fontColor(Color.Black) 498 Button('OK') 499 .onClick(() => { 500 if (this.controller != undefined) { 501 this.inputValue = this.textValue; 502 this.controller.close(); 503 } 504 }).backgroundColor(0xffffff).fontColor(Color.Red) 505 }.margin({ bottom: 10 }) 506 507 Button('Open Second Dialog Box') 508 .margin(20) 509 }.borderRadius(10) 510 // When using the border or cornerRadius attribute, use it together with the borderRadius attribute. 511 } 512} 513@Entry 514@Component 515struct CustomDialogUser { 516 @State textValue: string = ''; 517 @State inputValue: string = 'click me'; 518 dialogController: CustomDialogController | null = new CustomDialogController({ 519 builder: CustomDialogExample({ 520 textValue: $textValue, 521 inputValue: $inputValue 522 }), 523 cancel: this.exitApp, 524 autoCancel: true, 525 onWillDismiss: (dismissDialogAction: DismissDialogAction)=> { 526 console.info("reason=" + JSON.stringify(dismissDialogAction.reason)); 527 console.log("dialog onWillDismiss"); 528 if (dismissDialogAction.reason == DismissReason.PRESS_BACK) { 529 dismissDialogAction.dismiss(); 530 } 531 if (dismissDialogAction.reason == DismissReason.TOUCH_OUTSIDE) { 532 dismissDialogAction.dismiss(); 533 } 534 }, 535 alignment: DialogAlignment.Bottom, 536 offset: { dx: 0, dy: -20 }, 537 gridCount: 4, 538 customStyle: false, 539 cornerRadius: 10, 540 enableHoverMode: true, 541 hoverModeArea: HoverModeAreaType.TOP_SCREEN 542 }) 543 544 // Set dialogController to null when the custom component is about to be destroyed. 545 aboutToDisappear() { 546 this.dialogController = null; // Set dialogController to null. 547 } 548 549 exitApp() { 550 console.info('Click the callback in the blank area'); 551 } 552 553 build() { 554 Column() { 555 Button(this.inputValue) 556 .onClick(() => { 557 if (this.dialogController != null) { 558 this.dialogController.open(); 559 } 560 }).backgroundColor(0x317aff) 561 }.width('100%').margin({ top: 5 }) 562 } 563} 564``` 565 566 567