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>Value range: an integer no less than 0<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 subwindow 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 | 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| levelOrder<sup>18+</sup> | [LevelOrder](../js-apis-promptAction.md#levelorder18) | No | Display order of the dialog box.<br>**NOTE**<br>- Default value: **LevelOrder.clamp(0)**<br>- Dynamic updating is not supported.<br>**Atomic service API**: This API can be used in atomic services since API version 18.| 67 68> **NOTE** 69> 70> - Pressing the Back or ESC key closes the dialog box. 71> - If the dialog box reaches its maximum allowable height on the screen when avoiding the soft keyboard, it reduces its height to fit. 72> 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. 73> - 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. 74> 75> - 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). 76 77## DismissDialogAction<sup>12+</sup> 78 79Provides information about the action to dismiss the dialog box. 80 81**Atomic service API**: This API can be used in atomic services since API version 12. 82 83**System capability**: SystemCapability.ArkUI.ArkUI.Full 84 85### Properties 86 87| Name | Type | Readable| Writable| Description | 88| ------- | ------------------------------------------------------------ | ---- | ---- | ------------------------------------------------------------ | 89| dismiss | Callback<void> | No | No | Callback for dismissing the dialog box. This API is called only when the dialog box needs to be exited.| 90| 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.| 91 92## CustomDialogController 93 94**Atomic service API**: This API can be used in atomic services since API version 11. 95 96### Objects to Import 97 98```ts 99dialogController : CustomDialogController | null = new CustomDialogController(CustomDialogControllerOptions) 100``` 101> **NOTE** 102> 103> **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. 104 105### constructor 106 107constructor(value: CustomDialogControllerOptions) 108 109Constructor for a custom dialog box. 110 111**Atomic service API**: This API can be used in atomic services since API version 11. 112 113**System capability**: SystemCapability.ArkUI.ArkUI.Full 114 115**Parameters** 116 117| Name| Type | Mandatory| Description | 118| ------ | ------------------------------------------------------------ | ---- | ---------------------- | 119| value | [CustomDialogControllerOptions](#customdialogcontrolleroptions) | Yes | Parameters of the custom dialog box.| 120 121### open 122 123open() 124 125Opens 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. 126 127**Atomic service API**: This API can be used in atomic services since API version 11. 128 129**System capability**: SystemCapability.ArkUI.ArkUI.Full 130 131 132### close 133 134close() 135 136**Atomic service API**: This API can be used in atomic services since API version 11. 137 138**System capability**: SystemCapability.ArkUI.ArkUI.Full 139 140 141Closes the custom dialog box. If the dialog box is closed, this API does not take effect. 142 143## Example 144 145### Example 1: Opening Nested Dialog Boxes 146 147This example demonstrates how to open one or more custom dialog boxes within another custom dialog box. 148 149```ts 150// xxx.ets 151@CustomDialog 152struct CustomDialogExampleTwo { 153 controllerTwo?: CustomDialogController 154 build() { 155 Column() { 156 Text('I'm the second dialog box') 157 .fontSize(30) 158 .height(100) 159 Button('Close Second Dialog Box') 160 .onClick(() => { 161 if (this.controllerTwo != undefined) { 162 this.controllerTwo.close() 163 } 164 }) 165 .margin(20) 166 } 167 } 168} 169@CustomDialog 170@Component 171struct CustomDialogExample { 172 @Link textValue: string 173 @Link inputValue: string 174 dialogControllerTwo: CustomDialogController | null = new CustomDialogController({ 175 builder: CustomDialogExampleTwo(), 176 alignment: DialogAlignment.Bottom, 177 onWillDismiss:(dismissDialogAction: DismissDialogAction)=> { 178 console.info("reason=" + JSON.stringify(dismissDialogAction.reason)) 179 console.log("dialog onWillDismiss") 180 if (dismissDialogAction.reason == DismissReason.PRESS_BACK) { 181 dismissDialogAction.dismiss() 182 } 183 if (dismissDialogAction.reason == DismissReason.TOUCH_OUTSIDE) { 184 dismissDialogAction.dismiss() 185 } 186 }, 187 offset: { dx: 0, dy: -25 } }) 188 controller?: CustomDialogController 189 // 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. 190 cancel: () => void = () => { 191 } 192 confirm: () => void = () => { 193 } 194 195 build() { 196 Column() { 197 Text('Change text').fontSize(20).margin({ top: 10, bottom: 10 }) 198 TextInput({ placeholder: '', text: this.textValue }).height(60).width('90%') 199 .onChange((value: string) => { 200 this.textValue = value 201 }) 202 Text('Are you sure you want to change the text?').fontSize(16).margin({ bottom: 10 }) 203 Flex({ justifyContent: FlexAlign.SpaceAround }) { 204 Button('No') 205 .onClick(() => { 206 if (this.controller != undefined) { 207 this.controller.close() 208 this.cancel() 209 } 210 }).backgroundColor(0xffffff).fontColor(Color.Black) 211 Button('OK') 212 .onClick(() => { 213 if (this.controller != undefined) { 214 this.inputValue = this.textValue 215 this.controller.close() 216 this.confirm() 217 } 218 }).backgroundColor(0xffffff).fontColor(Color.Red) 219 }.margin({ bottom: 10 }) 220 221 Button('Open Second Dialog Box') 222 .onClick(() => { 223 if (this.dialogControllerTwo != null) { 224 this.dialogControllerTwo.open() 225 } 226 }) 227 .margin(20) 228 }.borderRadius(10) 229 // When using the border or cornerRadius attribute, use it together with the borderRadius attribute. 230 } 231} 232@Entry 233@Component 234struct CustomDialogUser { 235 @State textValue: string = '' 236 @State inputValue: string = 'click me' 237 dialogController: CustomDialogController | null = new CustomDialogController({ 238 builder: CustomDialogExample({ 239 cancel: ()=> { this.onCancel() }, 240 confirm: ()=> { this.onAccept() }, 241 textValue: $textValue, 242 inputValue: $inputValue 243 }), 244 cancel: this.exitApp, 245 autoCancel: true, 246 onWillDismiss:(dismissDialogAction: DismissDialogAction)=> { 247 console.info("reason=" + JSON.stringify(dismissDialogAction.reason)) 248 console.log("dialog onWillDismiss") 249 if (dismissDialogAction.reason == DismissReason.PRESS_BACK) { 250 dismissDialogAction.dismiss() 251 } 252 if (dismissDialogAction.reason == DismissReason.TOUCH_OUTSIDE) { 253 dismissDialogAction.dismiss() 254 } 255 }, 256 alignment: DialogAlignment.Bottom, 257 offset: { dx: 0, dy: -20 }, 258 gridCount: 4, 259 customStyle: false, 260 cornerRadius: 10, 261 }) 262 263 // Set dialogController to null when the custom component is about to be destroyed. 264 aboutToDisappear() { 265 this.dialogController = null // Set dialogController to null. 266 } 267 268 onCancel() { 269 console.info('Callback when the first button is clicked') 270 } 271 272 onAccept() { 273 console.info('Callback when the second button is clicked') 274 } 275 276 exitApp() { 277 console.info('Click the callback in the blank area') 278 } 279 build() { 280 Column() { 281 Button(this.inputValue) 282 .onClick(() => { 283 if (this.dialogController != null) { 284 this.dialogController.open() 285 } 286 }).backgroundColor(0x317aff) 287 }.width('100%').margin({ top: 5 }) 288 } 289} 290``` 291 292 293 294### Example 2: Opening a Dialog Box Outside the Main Window 295 296This example demonstrates how to configure a dialog box to display outside the main window on a 2-in-1 device by setting **showInSubWindow** to **true**. 297 298```ts 299// xxx.ets 300@CustomDialog 301struct CustomDialogExample { 302 controller?: CustomDialogController 303 cancel: () => void = () => { 304 } 305 confirm: () => void = () => { 306 } 307 build() { 308 Column() { 309 Text('Dialog box outside the main window') 310 .fontSize(30) 311 .height(100) 312 Button('Close') 313 .onClick(() => { 314 if (this.controller != undefined) { 315 this.controller.close() 316 } 317 }) 318 .margin(20) 319 } 320 } 321} 322@Entry 323@Component 324struct CustomDialogUser { 325 dialogController: CustomDialogController | null = new CustomDialogController({ 326 builder: CustomDialogExample({ 327 cancel: ()=> { this.onCancel() }, 328 confirm: ()=> { this.onAccept() } 329 }), 330 cancel: this.existApp, 331 autoCancel: true, 332 onWillDismiss:(dismissDialogAction: DismissDialogAction)=> { 333 console.info("reason=" + JSON.stringify(dismissDialogAction.reason)) 334 console.log("dialog onWillDismiss") 335 if (dismissDialogAction.reason == DismissReason.PRESS_BACK) { 336 dismissDialogAction.dismiss() 337 } 338 if (dismissDialogAction.reason == DismissReason.TOUCH_OUTSIDE) { 339 dismissDialogAction.dismiss() 340 } 341 }, 342 alignment: DialogAlignment.Center, 343 offset: { dx: 0, dy: -20 }, 344 gridCount: 4, 345 showInSubWindow: true, 346 isModal: true, 347 customStyle: false, 348 cornerRadius: 10, 349 }) 350 // Set dialogController to null when the custom component is about to be destroyed. 351 aboutToDisappear() { 352 this.dialogController = null // Set dialogController to null. 353 } 354 355 onCancel() { 356 console.info('Callback when the first button is clicked') 357 } 358 359 onAccept() { 360 console.info('Callback when the second button is clicked') 361 } 362 363 existApp() { 364 console.info('Click the callback in the blank area') 365 } 366 367 build() { 368 Column() { 369 Button('Click Me') 370 .onClick(() => { 371 if (this.dialogController != null) { 372 this.dialogController.open() 373 } 374 }).backgroundColor(0x317aff) 375 }.width('100%').margin({ top: 5 }) 376 } 377} 378``` 379 380 381 382### Example 3: Setting the Dialog Box Style 383This example demonstrates how to set styles of a custom dialog box, including the width, height, background color, and shadow. 384```ts 385// xxx.ets 386@CustomDialog 387struct CustomDialogExample { 388 controller?: CustomDialogController 389 cancel: () => void = () => { 390 } 391 confirm: () => void = () => { 392 } 393 build() { 394 Column() { 395 Text('This is a custom dialog box') 396 .fontSize(30) 397 .height(100) 398 Button('Close') 399 .onClick(() => { 400 if (this.controller != undefined) { 401 this.controller.close() 402 } 403 }) 404 .margin(20) 405 } 406 } 407} 408@Entry 409@Component 410struct CustomDialogUser { 411 dialogController: CustomDialogController | null = new CustomDialogController({ 412 builder: CustomDialogExample({ 413 cancel: ()=> { this.onCancel() }, 414 confirm: ()=> { this.onAccept() } 415 }), 416 cancel: this.existApp, 417 autoCancel: true, 418 onWillDismiss:(dismissDialogAction: DismissDialogAction)=> { 419 console.info("reason=" + JSON.stringify(dismissDialogAction.reason)) 420 console.log("dialog onWillDismiss") 421 if (dismissDialogAction.reason == DismissReason.PRESS_BACK) { 422 dismissDialogAction.dismiss() 423 } 424 if (dismissDialogAction.reason == DismissReason.TOUCH_OUTSIDE) { 425 dismissDialogAction.dismiss() 426 } 427 }, 428 alignment: DialogAlignment.Center, 429 offset: { dx: 0, dy: -20 }, 430 customStyle: false, 431 cornerRadius: 20, 432 width: 300, 433 height: 200, 434 borderWidth: 1, 435 borderStyle: BorderStyle.Dashed,// borderStyle must be used with borderWidth in pairs. 436 borderColor: Color.Blue,// borderColor must be used with borderWidth in pairs. 437 backgroundColor: Color.White, 438 shadow: ({ radius: 20, color: Color.Grey, offsetX: 50, offsetY: 0}), 439 }) 440 // Set dialogController to null when the custom component is about to be destroyed. 441 aboutToDisappear() { 442 this.dialogController = null // Set dialogController to null. 443 } 444 445 onCancel() { 446 console.info('Callback when the first button is clicked') 447 } 448 449 onAccept() { 450 console.info('Callback when the second button is clicked') 451 } 452 453 existApp() { 454 console.info('Click the callback in the blank area') 455 } 456 457 build() { 458 Column() { 459 Button('Click Me') 460 .onClick(() => { 461 if (this.dialogController != null) { 462 this.dialogController.open() 463 } 464 }).backgroundColor(0x317aff) 465 }.width('100%').margin({ top: 5 }) 466 } 467} 468``` 469 470 471 472### Example 4: Configuring a Dialog Box in the Hover State 473 474This example demonstrates how to set the layout area of a dialog box in the hover state on a foldable device. 475 476```ts 477@CustomDialog 478@Component 479struct CustomDialogExample { 480 @Link textValue: string; 481 @Link inputValue: string; 482 controller?: CustomDialogController; 483 484 build() { 485 Column() { 486 Text('Change text').fontSize(20).margin({ top: 10, bottom: 10 }) 487 TextInput({ placeholder: '', text: this.textValue }).height(60).width('90%') 488 .onChange((value: string) => { 489 this.textValue = value; 490 }) 491 Text('Are you sure you want to change the text?').fontSize(16).margin({ bottom: 10 }) 492 Flex({ justifyContent: FlexAlign.SpaceAround }) { 493 Button('No') 494 .onClick(() => { 495 if (this.controller != undefined) { 496 this.controller.close(); 497 } 498 }).backgroundColor(0xffffff).fontColor(Color.Black) 499 Button('OK') 500 .onClick(() => { 501 if (this.controller != undefined) { 502 this.inputValue = this.textValue; 503 this.controller.close(); 504 } 505 }).backgroundColor(0xffffff).fontColor(Color.Red) 506 }.margin({ bottom: 10 }) 507 508 Button('Open Second Dialog Box') 509 .margin(20) 510 }.borderRadius(10) 511 // When using the border or cornerRadius attribute, use it together with the borderRadius attribute. 512 } 513} 514@Entry 515@Component 516struct CustomDialogUser { 517 @State textValue: string = ''; 518 @State inputValue: string = 'click me'; 519 dialogController: CustomDialogController | null = new CustomDialogController({ 520 builder: CustomDialogExample({ 521 textValue: $textValue, 522 inputValue: $inputValue 523 }), 524 cancel: this.exitApp, 525 autoCancel: true, 526 onWillDismiss: (dismissDialogAction: DismissDialogAction)=> { 527 console.info("reason=" + JSON.stringify(dismissDialogAction.reason)); 528 console.log("dialog onWillDismiss"); 529 if (dismissDialogAction.reason == DismissReason.PRESS_BACK) { 530 dismissDialogAction.dismiss(); 531 } 532 if (dismissDialogAction.reason == DismissReason.TOUCH_OUTSIDE) { 533 dismissDialogAction.dismiss(); 534 } 535 }, 536 alignment: DialogAlignment.Bottom, 537 offset: { dx: 0, dy: -20 }, 538 gridCount: 4, 539 customStyle: false, 540 cornerRadius: 10, 541 enableHoverMode: true, 542 hoverModeArea: HoverModeAreaType.TOP_SCREEN 543 }) 544 545 // Set dialogController to null when the custom component is about to be destroyed. 546 aboutToDisappear() { 547 this.dialogController = null; // Set dialogController to null. 548 } 549 550 exitApp() { 551 console.info('Click the callback in the blank area'); 552 } 553 554 build() { 555 Column() { 556 Button(this.inputValue) 557 .onClick(() => { 558 if (this.dialogController != null) { 559 this.dialogController.open(); 560 } 561 }).backgroundColor(0x317aff) 562 }.width('100%').margin({ top: 5 }) 563 } 564} 565``` 566 567 568<!--no_check-->