• 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
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                        | () =&gt; 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&lt;void&gt;                                         | 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![en-us_image_custom](figures/en-us_image_custom.gif)
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![en-us_image_custom-showinsubwindow](figures/en-us_image_custom-showinsubwindow.jpg)
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![en-us_image_custom_style](figures/en-us_image_custom_style.gif)
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![en-us_image_custom](figures/en-us_image_custom_hovermode.gif)
567