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 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 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 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 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 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 477