• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Modal Transition
2
3
4Modal transition is a type of transition achieved by a modal – a view that appears on top of the current view while the current view remains.
5
6
7**Table 1** Modal transition APIs
8| API                                      | Description               | Usage                                    |
9| ---------------------------------------- | ----------------- | ---------------------------------------- |
10| [bindContentCover](../reference/arkui-ts/ts-universal-attributes-modal-transition.md) | Binds a modal to the component.       | Use this API to display a custom modal. It can work with the transition animation and shared element animation to implement complex transition animation effects, for example, displaying an image in full in the modal upon the click of a thumbnail.|
11| [bindSheet](../reference/arkui-ts/ts-universal-attributes-sheet-transition.md) | Binds a sheet to the component.         | Use this API to display a custom sheet, for example, a sharing confirmation dialog box.                         |
12| [bindMenu](../reference/arkui-ts/ts-universal-attributes-menu.md) | Binds a menu to the component, which is displayed when the component is clicked.    | Use this API where a menu is required, for example, for the plus sign (+), a common menu indicator in applications.                |
13| [bindContextMenu](../reference/arkui-ts/ts-universal-attributes-menu.md) | Binds a context menu to the component, which is displayed when the user long-presses or right-clicks the component.| Use this API for components that bounce up when long-pressed, for example, home screen icons.            |
14| [bindPopup](../reference/arkui-ts/ts-universal-attributes-popup.md) | Binds a popup to the component.       | Use this API to display a popup containing additional information about a component when the component is clicked.              |
15| if                                       | Adds or deletes the component.     | Use this API to display a temporary page in a certain state. In this mode, the return navigation needs to be implemented with a listener. |
16
17
18## Creating Modal Transition with bindContentCover
19
20You can bind a full-screen modal to a component through the [bindContentCover](../reference/arkui-ts/ts-universal-attributes-modal-transition.md) attribute. Better yet, with the **ModalTransition** parameter, you can apply a transition effect for when the component is inserted or deleted.
21
221. Define [bindContentCover](../reference/arkui-ts/ts-universal-attributes-modal-transition.md).
23
242. Define the modal view.
25
26   ```ts
27   // Use @Builder to build a modal view.
28   @Builder MyBuilder() {
29     Column() {
30       Text('my model view')
31     }
32     // Use the transition API to implement the transition animation for component appearance and disappearance. The transition API must be added to the first component of the builder.
33     .transition(TransitionEffect.translate(y:300).animation({ curve: curves.springMotion(0.6, 0.8) }))
34   }
35   ```
36
373. Call the modal API to display the modal. Implement an animation by using the animation or shared element transition APIs.
38
39   ```ts
40    class PresentTmp{
41      isPresent: boolean = false;
42      set(){
43        this.isPresent = !this.isPresent;
44      }
45    }
46   // Define the state variable to control the visibility of the modal.
47   @State isPresent: boolean = false;
48
49   Button('Click to present model view')
50     // Bind the modal to the component. ModalTransition indicates the transition mode of the modal. The value None means no transition animation for the modal.
51     .bindContentCover(this.isPresent, this.MyBuilder, ModalTransition.NONE)
52     .onClick(() => {
53       // Change the state variable to display the modal.
54       let setPre:PresentTmp = new PresentTmp()
55       setPre.set()
56     })
57   ```
58
59
60Below is the complete sample code and effect.
61
62
63
64```ts
65import curves from '@ohos.curves';
66
67@Entry
68@Component
69struct BindContentCoverDemo {
70  // Step 1: Define bindContentCover.
71  // Define the state variable to control the visibility of the modal.
72  @State isPresent: boolean = false;
73
74  // Step 2: Define the modal view.
75  // Use @Builder to build a modal view.
76  @Builder MyBuilder() {
77    Column() {
78      Column() {
79        Column() {
80          Text('back')
81            .fontSize(24)
82            .fontColor(Color.White)
83        }
84        .justifyContent(FlexAlign.Center)
85        .width(100)
86        .height(100)
87        .borderRadius(5)
88        .backgroundColor(0xf56c6c)
89        .onClick(() => {
90          this.isPresent = false;
91        })
92      }
93      .height('100%')
94      .width('100%')
95      .backgroundColor(0x909399)
96      .justifyContent(FlexAlign.Center)
97      .border({
98        radius: {
99          topLeft: 15,
100          topRight: 15,
101        }
102      })
103    }
104    .height('100%')
105    .justifyContent(FlexAlign.End)
106    // Use the transition API to implement the transition animation for component appearance and disappearance.
107    .transition(TransitionEffect.translate({ y: 1000 }).animation({ curve: curves.springMotion(0.6, 0.8) }))
108  }
109
110  build() {
111    Column() {
112      Column() {
113        Text('Click Me')
114          .fontSize(24)
115          .fontColor(Color.White)
116      }
117      // Step 3: Call the modal API to display the modal. Implement an animation by using the animation or shared element transition APIs.
118      .onClick(() => {
119        // Change the state variable to display the modal.
120        this.isPresent = !this.isPresent;
121      })
122      // Bind a modal to the component. ModalTransition.DEFAULT means to use the slide-up and slide-down animation type.
123      .bindContentCover(this.isPresent, this.MyBuilder(), ModalTransition.DEFAULT)
124      .justifyContent(FlexAlign.Center)
125      .backgroundColor(0XF56C6C)
126      .width(100)
127      .height(100)
128      .borderRadius(5)
129    }
130    .justifyContent(FlexAlign.Center)
131    .width('100%')
132    .height('100%')
133  }
134}
135```
136
137
138
139![en-us_image_0000001646921957](figures/en-us_image_0000001646921957.gif)
140
141
142
143## Creating Sheet Transition with bindSheet
144
145You can bind a sheet to a component through the [bindSheet](../reference/arkui-ts/ts-universal-attributes-sheet-transition.md) attribute. You can also set the sheet to the preset or custom height for when the component is inserted. The process of creating a sheet transition is basically the same as that of creating a modal transition.
146
147Below is the complete sample code and effect.
148
149
150```ts
151@Entry
152@Component
153struct BindSheetDemo {
154
155  // Define the state variable to control the sheet height.
156  @State sheetHeight: number|SheetSize|null|undefined = 300;
157  // Define the state variable to control the visibility of the drag bar.
158  @State showDragBar: boolean = true;
159
160  // Use @Builder to build a sheet view.
161  @Builder myBuilder() {
162    Column() {
163      Button("change height")
164        .margin(10)
165        .fontSize(20)
166        .onClick(() => {
167          this.sheetHeight = 500;
168        })
169
170      Button("Set Illegal height")
171        .margin(10)
172        .fontSize(20)
173        .onClick(() => {
174          this.sheetHeight = null;
175        })
176
177      Button("close dragbar")
178        .margin(10)
179        .fontSize(20)
180        .onClick(() => {
181          this.showDragBar = !this.showDragBar;
182        })
183      Button("close modal 1")
184        .margin(10)
185        .fontSize(20)
186        .onClick(() => {
187          this.isPresent = false;
188        })
189    }
190    .width('100%')
191    .height('100%')
192  }
193
194  // Define the state variable to control the visibility of the sheet.
195  @State isPresent: boolean = false;
196
197  build() {
198    Column() {
199      if(this.sheetHeight){
200        Button("Click to present sheet view")
201        .onClick(() => {
202          // Change the state variable to display the modal.
203          this.isPresent = !this.isPresent;
204        })
205        .fontSize(20)
206        .margin(10)
207          // Bind the sheet to the component. You can specify the sheet height and whether to display the drag bar.
208        .bindSheet(this.isPresent, this.myBuilder(), { height: this.sheetHeight, dragBar: this.showDragBar })
209      }
210    }
211    .justifyContent(FlexAlign.Center)
212    .width('100%')
213    .height('100%')
214  }
215}
216```
217
218![en-us_image_0000001599977924](figures/en-us_image_0000001599977924.gif)
219
220
221## Creating a Menu with bindMenu
222
223You can bind a menu to component through the [bindMenu](../reference/arkui-ts/ts-universal-attributes-menu.md) attribute. The menu can then be triggered by clicking. Below is the complete sample code and effect.
224
225
226```ts
227class BMD{
228  value:ResourceStr = ''
229  action:() => void = () => {}
230}
231@Entry
232@Component
233struct BindMenuDemo {
234
235  // Step 1: Define a data array to represent menu items.
236  @State items:BMD[] = [
237    {
238      value:'Menu item 1',
239      action: () => {
240        console.info('handle Menu1 select')
241      }
242    },
243    {
244      value:'Menu item 2',
245      action: () => {
246        console.info('handle Menu2 select')
247      }
248    },
249  ]
250
251  build() {
252    Column() {
253      Button('click')
254        .backgroundColor(0x409eff)
255        .borderRadius(5)
256          // Step 2: Bind the menu data to the component through bindMenu.
257        .bindMenu(this.items)
258    }
259    .justifyContent(FlexAlign.Center)
260    .width('100%')
261    .height(437)
262  }
263}
264```
265
266![en-us_image_0000001599643478](figures/en-us_image_0000001599643478.gif)
267
268
269## Creating a Context Menu with bindContextMenu
270
271You can bind a context menu to component through the [bindContextMenu](../reference/arkui-ts/ts-universal-attributes-menu.md) attribute. The menu can then be triggered by long-pressing or right-clicking.
272
273Below is the complete sample code and effect.
274
275
276```ts
277@Entry
278@Component
279struct BindContextMenuDemo {
280  private num: number[] = [1, 2, 3, 4];
281  private colors: Color[] = [0x67C23A, 0xE6A23C, 0xf56c6c, 0x909399];
282  // Use @Builder to build custom menu items.
283  @Builder MyMenu() {
284    Row() {
285      Column() {
286        ForEach(this.num, (item: number, index: number = 0) => {
287          Row() {
288              Text(item.toString())
289                .fontSize(20)
290                .fontColor(Color.White)
291            }
292            .backgroundColor(this.colors[index])
293            .width('100%')
294            .aspectRatio(2)
295            .justifyContent(FlexAlign.Center)
296        })
297      }
298      .width('100%')
299    }
300    .width(150)
301    .justifyContent(FlexAlign.Center)
302    .padding(5)
303  }
304
305  build() {
306    Column() {
307      Column() {
308        Text('longPress')
309          .fontSize(20)
310          .fontColor(Color.White)
311      }
312      .justifyContent(FlexAlign.Center)
313      .width(170)
314      .height(50)
315      .bindContextMenu(this.MyMenu, ResponseType.LongPress)
316      .backgroundColor(0xf56c6c)
317      .borderRadius(5)
318    }
319    .justifyContent(FlexAlign.Center)
320    .width('100%')
321    .height(437)
322  }
323}
324```
325
326![en-us_image_0000001600137920](figures/en-us_image_0000001600137920.gif)
327
328
329## Creating a Popup with bindPopUp
330
331You can bind a popup to a component through the [bindpopup](../reference/arkui-ts/ts-universal-attributes-popup.md) attribute, specifying its content, interaction logic, and display status.
332
333Below is the complete sample code and effect.
334
335
336```ts
337@Entry
338@Component
339struct BindPopupDemo {
340
341  // Step 1: Define the state variable to control the visibility of the popup.
342  @State customPopup: boolean = false;
343
344  // Step 2: Use @Builder to build a custom popup.
345  @Builder popupBuilder() {
346    Column({ space: 2 }) {
347      Row().width(64)
348        .height(64)
349        .backgroundColor(0x409eff)
350      Text('Popup')
351        .fontSize(10)
352        .fontColor(Color.White)
353    }
354    .justifyContent(FlexAlign.SpaceAround)
355    .width(100)
356    .height(100)
357    .padding(5)
358  }
359
360  build() {
361    Column() {
362
363      Button('click')
364        // Step 4: Add a click event to control the visibility of the popup.
365        .onClick(() => {
366          this.customPopup = !this.customPopup;
367        })
368        .backgroundColor(0xf56c6c)
369          // Step 5: Bind the popup to the component through bindPopup.
370        .bindPopup(this.customPopup, {
371          builder: this.popupBuilder,
372          placement: Placement.Top,
373          maskColor: 0x33000000,
374          popupColor: 0xf56c6c,
375          enableArrow: true,
376          onStateChange: (e) => {
377            if (!e.isVisible) {
378              this.customPopup = false;
379            }
380          }
381        })
382    }
383    .justifyContent(FlexAlign.Center)
384    .width('100%')
385    .height(437)
386  }
387}
388```
389
390
391
392![en-us_image_0000001649282285](figures/en-us_image_0000001649282285.gif)
393
394
395## Creating Modal Transition with if
396
397In addition to the preceding modal transition APIs, you can also use the **if** syntax to create a modal transition, eliminating the need for binding to the component and listening for state variable changes.
398
399Below is the complete sample code and effect.
400
401
402```ts
403@Entry
404@Component
405struct ModalTransition1 {
406
407  // Step 1: Define a state variable to control page display.
408  @State isShow: boolean = false;
409
410  build() {
411    // Step 2: Define a stack layout to display the current view and modal view.
412    Stack() {
413      Column() {
414        Text('Page1')
415          .fontSize(40)
416          .fontColor(Color.White)
417          .fontWeight(FontWeight.Bolder)
418
419        Text('Click to transition')
420          .fontSize(15)
421          .fontColor(Color.White)
422      }
423      .justifyContent(FlexAlign.Center)
424      .width('100%')
425      .height('100%')
426      .linearGradient({
427        colors: [
428          [0xf56c6c, 0.0],
429          [0xffffff, 1.0]
430        ]
431      })
432      // Step 3: Change the state variable to display the modal view.
433      .onClick(() => {
434        animateTo({ duration: 500 }, () => {
435          this.isShow = !this.isShow;
436        })
437      })
438
439      // Step 4: Define the modal view in if and display it at the top layer. Use if to control the appearance and disappearance of the modal view.
440      if (this.isShow) {
441        Column() {
442          Text('Page2')
443            .fontSize(40)
444            .fontColor(Color.Gray)
445            .fontWeight(FontWeight.Bolder)
446
447          Text('Click to transition')
448            .fontSize(15)
449            .fontColor(Color.Gray)
450        }
451        .justifyContent(FlexAlign.Start)
452        .width('100%')
453        .height('100%')
454        .linearGradient({
455          colors: [
456            [0xffffff, 0.0],
457            [0x409eff, 1.0]
458          ]
459        })
460        // Step 5: Define the mode in which the modal view disappears.
461        .transition(TransitionEffect.OPACITY.combine(TransitionEffect.rotate({ angle: 90, y: 1 })))
462        .onClick(() => {
463          animateTo({ duration: 500 }, () => {
464            this.isShow = !this.isShow;
465          })
466        })
467      }
468
469    }
470    .width('100%')
471    .height('100%')
472  }
473}
474```
475
476![en-us_image_0000001597792146](figures/en-us_image_0000001597792146.gif)
477