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