• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Custom Dialog Box (CustomDialog)
2
3
4A custom dialog box is a dialog box you customize by using APIs of the **CustomDialogController** class. It can be used for user interactions, showing an ad, prize, alert, software update message, and more. For details, see [Custom Dialog Box](../reference/apis-arkui/arkui-ts/ts-methods-custom-dialog-box.md).
5
6
7## Creating a Custom Dialog Box
8
91. Use the \@CustomDialog decorator to create a custom dialog box.
10
112. Set the content for the \@CustomDialog decorated dialog box.
12
13   ```ts
14   @CustomDialog
15   struct CustomDialogExample {
16     controller: CustomDialogController = new CustomDialogController({
17       builder: CustomDialogExample({}),
18     })
19
20     build() {
21       Column() {
22         Text ('I am content')
23           .fontSize(20)
24           .margin({ top: 10, bottom: 10 })
25       }
26     }
27   }
28   ```
29
303. Create a builder that is bound to the decorator.
31
32   ```ts
33    @Entry
34    @Component
35    struct CustomDialogUser {
36      dialogController: CustomDialogController = new CustomDialogController({
37        builder: CustomDialogExample(),
38      })
39    }
40   ```
41
424. Click the component bound to the **onClick** event to display the dialog box.
43
44   ```ts
45   @Entry
46   @Component
47   struct CustomDialogUser {
48     dialogController: CustomDialogController = new CustomDialogController({
49       builder: CustomDialogExample(),
50     })
51
52     build() {
53       Column() {
54         Button('click me')
55           .onClick(() => {
56             this.dialogController.open()
57           })
58       }.width('100%').margin({ top: 5 })
59     }
60   }
61   ```
62
63   ![en-us_image_0000001562700493](figures/en-us_image_0000001562700493.png)
64
65
66## Interaction with Custom Dialog Box
67
68Custom dialog boxes can be used for data interactions to complete a series of response operations.
69
70
711. Add buttons in the \@CustomDialog decorator structure and add data functions.
72
73   ```ts
74   @CustomDialog
75   struct CustomDialogExample {
76     cancel?: () => void
77     confirm?: () => void
78     controller: CustomDialogController
79
80     build() {
81       Column() {
82         Text('I am content') .fontSize(20).margin({ top: 10, bottom: 10 })
83         Flex({ justifyContent: FlexAlign.SpaceAround }) {
84           Button('cancel')
85             .onClick(() => {
86               this.controller.close()
87               if (this.cancel) {
88                 this.cancel()
89               }
90             }).backgroundColor(0xffffff).fontColor(Color.Black)
91           Button('confirm')
92             .onClick(() => {
93               this.controller.close()
94               if (this.confirm) {
95                 this.confirm()
96               }
97             }).backgroundColor(0xffffff).fontColor(Color.Red)
98         }.margin({ bottom: 10 })
99       }
100     }
101   }
102   ```
103
1042. Receive the page in the builder and create corresponding function operations.
105
106     ```ts
107   @Entry
108   @Component
109   struct CustomDialogUser {
110       dialogController: CustomDialogController = new CustomDialogController({
111         builder: CustomDialogExample({
112           cancel: ()=> { this.onCancel() },
113           confirm: ()=> { this.onAccept() },
114         }),
115       })
116
117       onCancel() {
118         console.info('Callback when the first button is clicked')
119       }
120
121       onAccept() {
122         console.info('Callback when the second button is clicked')
123       }
124
125       build() {
126         Column() {
127           Button('click me')
128             .onClick(() => {
129               this.dialogController.open()
130             })
131         }.width('100%').margin({ top: 5 })
132       }
133     }
134   ```
135
136      ![en-us_image_0000001511421320](figures/en-us_image_0000001511421320.png)
137
138   3. Use the button in the dialog box to implement route redirection and obtain the parameters passed in from the redirection target page.
139
140   ```ts
141   // Index.ets
142   import { router } from '@kit.ArkUI';
143
144   @CustomDialog
145   struct CustomDialogExample {
146     @Link textValue: string
147     controller?: CustomDialogController
148     cancel: () => void = () => {
149     }
150     confirm: () => void = () => {
151     }
152
153     build() {
154       Column({ space: 20 }) {
155         if (this.textValue != '') {
156           Text(`Content of the second page: ${this.textValue}`)
157             .fontSize(20)
158         } else {
159           Text('Obtain the content of the second page?')
160             .fontSize(20)
161         }
162         Flex({ justifyContent: FlexAlign.SpaceAround }) {
163           Button('Cancel')
164             .onClick(() => {
165               if (this.controller != undefined) {
166                 this.controller.close()
167                 this.cancel()
168               }
169             }).backgroundColor(0xffffff).fontColor(Color.Black)
170           Button('Obtain')
171             .onClick(() => {
172               if (this.controller != undefined && this.textValue != '') {
173                 this.controller.close()
174               } else if (this.controller != undefined) {
175                 router.pushUrl({
176                   url: 'pages/Index2'
177                 })
178                 this.controller.close()
179               }
180             }).backgroundColor(0xffffff).fontColor(Color.Red)
181         }.margin({ bottom: 10 })
182       }.borderRadius(10).padding({ top: 20 })
183     }
184   }
185
186   @Entry
187   @Component
188   struct CustomDialogUser {
189     @State textValue: string = ''
190     dialogController: CustomDialogController | null = new CustomDialogController({
191       builder: CustomDialogExample({
192         cancel: () => {
193           this.onCancel()
194         },
195         confirm: () => {
196           this.onAccept()
197         },
198         textValue: $textValue
199       })
200     })
201
202     // Set dialogController to null when the custom component is about to be destroyed.
203     aboutToDisappear() {
204       this.dialogController = null // Set dialogController to null.
205     }
206
207     onPageShow() {
208       const params = router.getParams() as Record<string, string>; // Obtain the passed parameter object.
209       if (params) {
210         this.dialogController?.open()
211         this.textValue = params.info as string; // Obtain the value of the id attribute.
212       }
213     }
214
215     onCancel() {
216       console.info('Callback when the first button is clicked')
217     }
218
219     onAccept() {
220       console.info('Callback when the second button is clicked')
221     }
222
223     exitApp() {
224       console.info('Click the callback in the blank area')
225     }
226
227     build() {
228       Column() {
229         Button('click me')
230           .onClick(() => {
231             if (this.dialogController != null) {
232               this.dialogController.open()
233             }
234           }).backgroundColor(0x317aff)
235       }.width('100%').margin({ top: 5 })
236     }
237   }
238   ```
239
240   ```ts
241   // Index2.ets
242   import { router } from '@kit.ArkUI';
243
244   @Entry
245   @Component
246   struct Index2 {
247     @State message: string =' Back';
248     build() {
249       Column() {
250         Button(this.message)
251           .fontSize(50)
252           .fontWeight(FontWeight.Bold).onClick(() => {
253           router.back({
254             url: 'pages/Index',
255             params: {
256               info: 'Hello World'
257             }
258           });
259         })
260       }.width('100%').height('100%').margin({ top: 20 })
261     }
262   }
263   ```
264
265   ![DialogRouter](figures/DialogRouter.gif)
266
267## Defining the Custom Dialog Box Animation
268
269You can define the custom dialog box animation, including its duration and speed, through **openAnimation**.
270
271```ts
272@CustomDialog
273struct CustomDialogExample {
274  controller?: CustomDialogController
275
276  build() {
277    Column() {
278      Text('Whether to change a text?').fontSize(16).margin({ bottom: 10 })
279    }
280  }
281}
282
283@Entry
284@Component
285struct CustomDialogUser {
286  @State textValue: string = ''
287  @State inputValue: string = 'click me'
288  dialogController: CustomDialogController | null = new CustomDialogController({
289    builder: CustomDialogExample(),
290    openAnimation: {
291      duration: 1200,
292      curve: Curve.Friction,
293      delay: 500,
294      playMode: PlayMode.Alternate,
295      onFinish: () => {
296        console.info('play end')
297      }
298    },
299    autoCancel: true,
300    alignment: DialogAlignment.Bottom,
301    offset: { dx: 0, dy: -20 },
302    gridCount: 4,
303    customStyle: false,
304    backgroundColor: 0xd9ffffff,
305    cornerRadius: 10,
306  })
307
308  // Set dialogController to null when the custom component is about to be destroyed.
309  aboutToDisappear() {
310    this.dialogController = null // Set dialogController to null.
311  }
312
313  build() {
314    Column() {
315      Button(this.inputValue)
316        .onClick(() => {
317          if (this.dialogController != null) {
318            this.dialogController.open()
319          }
320        }).backgroundColor(0x317aff)
321    }.width('100%').margin({ top: 5 })
322  }
323}
324```
325
326![openAnimator](figures/openAnimator.gif)
327
328## Nesting a Custom Dialog Box
329
330To nest a dialog box (dialog 2) within another dialog box (dialog 1), it is recommended that you define dialog 2 at the parent component of dialog 1 and open dialog 2 through the callback sent by the parent component to dialog 1.
331
332```ts
333@CustomDialog
334struct CustomDialogExampleTwo {
335  controllerTwo?: CustomDialogController
336  @State message: string = "I'm the second dialog box."
337  @State showIf: boolean = false;
338  build() {
339    Column() {
340      if (this.showIf) {
341        Text("Text")
342          .fontSize(30)
343          .height(100)
344      }
345      Text(this.message)
346        .fontSize(30)
347        .height(100)
348      Button("Create Text")
349        .onClick(()=>{
350          this.showIf = true;
351        })
352      Button ('Close Second Dialog Box')
353        .onClick(() => {
354          if (this.controllerTwo != undefined) {
355            this.controllerTwo.close()
356          }
357        })
358        .margin(20)
359    }
360  }
361}
362@CustomDialog
363struct CustomDialogExample {
364  openSecondBox?: ()=>void
365  controller?: CustomDialogController
366
367  build() {
368    Column() {
369      Button ('Open Second Dialog Box and close this box')
370        .onClick(() => {
371          this.controller!.close();
372          this.openSecondBox!();
373        })
374        .margin(20)
375    }.borderRadius(10)
376  }
377}
378@Entry
379@Component
380struct CustomDialogUser {
381  @State inputValue: string = 'Click Me'
382  dialogController: CustomDialogController | null = new CustomDialogController({
383    builder: CustomDialogExample({
384      openSecondBox: ()=>{
385        if (this.dialogControllerTwo != null) {
386          this.dialogControllerTwo.open()
387        }
388      }
389    }),
390    cancel: this.exitApp,
391    autoCancel: true,
392    alignment: DialogAlignment.Bottom,
393    offset: { dx: 0, dy: -20 },
394    gridCount: 4,
395    customStyle: false
396  })
397  dialogControllerTwo: CustomDialogController | null = new CustomDialogController({
398    builder: CustomDialogExampleTwo(),
399    alignment: DialogAlignment.Bottom,
400    offset: { dx: 0, dy: -25 } })
401
402  aboutToDisappear() {
403    this.dialogController = null
404    this.dialogControllerTwo = null
405  }
406
407  onCancel() {
408    console.info('Callback when the first button is clicked')
409  }
410
411  onAccept() {
412    console.info('Callback when the second button is clicked')
413  }
414
415  exitApp() {
416    console.info('Click the callback in the blank area')
417  }
418  build() {
419    Column() {
420      Button(this.inputValue)
421        .onClick(() => {
422          if (this.dialogController != null) {
423            this.dialogController.open()
424          }
425        }).backgroundColor(0x317aff)
426    }.width('100%').margin({ top: 5 })
427  }
428}
429```
430![nested_dialog](figures/nested_dialog.gif)
431
432If you define dialog 2 at dialog 1 instead, due to the parent-child relationship between custom dialog boxes on the state management side, you will not be able to create any component in dialog 2 once dialog 1 is destroyed (closed).
433
434