1# 全屏模态转场
2
3通过bindContentCover属性为组件绑定全屏模态页面,在组件插入和删除时可通过设置转场参数ModalTransition显示过渡动效。
4
5>  **说明:**
6>
7>  从API Version 10开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。
8>
9>  不支持横竖屏切换。
10>
11>  不支持路由跳转。
12
13## bindContentCover
14
15bindContentCover(isShow: Optional\<boolean\>, builder: CustomBuilder, options?: ContentCoverOptions)
16
17给组件绑定全屏模态页面,点击后显示模态页面。模态页面内容自定义,显示方式可设置无动画过渡,上下切换过渡以及透明渐变过渡方式。
18
19**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
20
21**系统能力:** SystemCapability.ArkUI.ArkUI.Full
22
23**参数:**
24
25| 参数名  | 类型                                        | 必填 | 说明                                                         |
26| ------- | ------------------------------------------- | ---- | ------------------------------------------------------------ |
27| isShow  | Optional\<boolean\>                         | 是   | 是否显示全屏模态页面。<br/>从API version 10开始,该参数支持[$$](../../../quick-start/arkts-two-way-sync.md)双向绑定变量。|
28| builder | [CustomBuilder](ts-types.md#custombuilder8) | 是   | 配置全屏模态页面内容。                                       |
29| options | [ContentCoverOptions](#contentcoveroptions) | 否   | 配置全屏模态页面的可选属性。                                 |
30
31## ContentCoverOptions
32继承自[BindOptions](ts-universal-attributes-sheet-transition.md#bindoptions)。
33| 名称              | 类型                                       | 必填   | 描述            |
34| --------------- | ---------------------------------------- | ---- | ------------- |
35| modalTransition | [ModalTransition](ts-types.md#modaltransition10) | 否    | 全屏模态页面的转场方式。<br />**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。  |
36| onWillDismiss<sup>12+</sup> | Callback&lt;[DismissContentCoverAction](#dismisscontentcoveraction12类型说明)&gt; | 否    | 全屏模态页面交互式关闭回调函数。<br/>**说明:**<br />当用户执行back事件关闭交互操作时,如果注册该回调函数,则不会立刻关闭。在回调函数中可以通过reason得到阻拦关闭页面的操作类型,从而根据原因选择是否关闭全屏模态页面。在onWillDismiss回调中,不能再做onWillDismiss拦截。 <br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。|
37| transition<sup>12+</sup> | [TransitionEffect](ts-transition-animation-component.md#transitioneffect10对象说明) | 否    | 全屏模态页面的转场方式。  <br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。|
38
39## DismissContentCoverAction<sup>12+</sup>类型说明
40
41**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
42
43| 名称              | 类型                                       | 必填   | 描述            |
44| --------------- | ---------------------------------------- | ---- | ------------- |
45| dismiss | function | 是    | 全屏模态页面关闭回调函数。开发者需要退出页面时调用。 |
46| reason | [DismissReason](ts-universal-attributes-popup.md#dismissreason12枚举说明) | 是    | 返回本次拦截全屏模态页面退出的事件原因。  |
47
48## 示例
49
50### 示例1(使用全屏模态转场)
51
52该示例主要演示通过bindContentCover来实现全屏模态转场。
53
54```ts
55// xxx.ets
56@Entry
57@Component
58struct ModalTransitionExample {
59  @State isShow: boolean = false
60  @State isShow2: boolean = false
61
62  @Builder
63  myBuilder2() {
64    Column() {
65      Button("close modal 2")
66        .margin(10)
67        .fontSize(20)
68        .onClick(() => {
69          this.isShow2 = false;
70        })
71    }
72    .width('100%')
73    .height('100%')
74  }
75
76  @Builder
77  myBuilder() {
78    Column() {
79      Button("transition modal 2")
80        .margin(10)
81        .fontSize(20)
82        .onClick(() => {
83          this.isShow2 = true;
84        }).bindContentCover(this.isShow2, this.myBuilder2(), {
85        modalTransition: ModalTransition.NONE,
86        backgroundColor: Color.Orange,
87        onWillAppear: () => {
88          console.log("BindContentCover onWillAppear.")
89        },
90        onAppear: () => {
91          console.log("BindContentCover onAppear.")
92        },
93        onWillDisappear: () => {
94          console.log("BindContentCover onWillDisappear.")
95        },
96        onDisappear: () => {
97          console.log("BindContentCover onDisappear.")
98        }
99      })
100
101      Button("close modal 1")
102        .margin(10)
103        .fontSize(20)
104        .onClick(() => {
105          this.isShow = false;
106        })
107    }
108    .width('100%')
109    .height('100%')
110    .justifyContent(FlexAlign.Center)
111  }
112
113  build() {
114    Column() {
115      Button("transition modal 1")
116        .onClick(() => {
117          this.isShow = true
118        })
119        .fontSize(20)
120        .margin(10)
121        .bindContentCover(this.isShow, this.myBuilder(), {
122          modalTransition: ModalTransition.NONE,
123          backgroundColor: Color.Pink,
124          onWillAppear: () => {
125            console.log("BindContentCover onWillAppear.")
126          },
127          onAppear: () => {
128            console.log("BindContentCover onAppear.")
129          },
130          onWillDisappear: () => {
131            console.log("BindContentCover onWillDisappear.")
132          },
133          onDisappear: () => {
134            console.log("BindContentCover onDisappear.")
135          }
136        })
137    }
138    .justifyContent(FlexAlign.Center)
139    .backgroundColor("#ff49c8ab")
140    .width('100%')
141    .height('100%')
142  }
143}
144```
145
146![zh-cn_full_screen_modal_none_1](figures/zh-cn_full_screen_modal_none_1.gif)
147
148### 示例2(自定义转场动画)
149
150全屏模态无动画转场模式下,自定义转场动画。
151
152```ts
153// xxx.ets
154import { curves } from '@kit.ArkUI';
155
156@Entry
157@Component
158struct ModalTransitionExample {
159  @State @Watch("isShow1Change") isShow: boolean = false
160  @State @Watch("isShow2Change") isShow2: boolean = false
161  @State isScale1: number = 1;
162  @State isScale2: number = 1;
163
164  isShow1Change() {
165    this.isShow ? this.isScale1 = 0.95 : this.isScale1 = 1
166  }
167
168  isShow2Change() {
169    this.isShow2 ? this.isScale2 = 0.95 : this.isScale2 = 1
170  }
171
172  @Builder
173  myBuilder2() {
174    Column() {
175      Button("close modal 2")
176        .margin(10)
177        .fontSize(20)
178        .onClick(() => {
179          this.isShow2 = false;
180        })
181    }
182    .width('100%')
183    .height('100%')
184  }
185
186  @Builder
187  myBuilder() {
188    Column() {
189      Button("transition modal 2")
190        .margin(10)
191        .fontSize(20)
192        .onClick(() => {
193          this.isShow2 = true;
194        }).bindContentCover(this.isShow2, this.myBuilder2(), {
195        modalTransition: ModalTransition.NONE,
196        backgroundColor: Color.Orange,
197        onWillAppear: () => {
198          console.log("BindContentCover onWillAppear.")
199        },
200        onAppear: () => {
201          console.log("BindContentCover onAppear.")
202        },
203        onWillDisappear: () => {
204          console.log("BindContentCover onWillDisappear.")
205        },
206        onDisappear: () => {
207          console.log("BindContentCover onDisappear.")
208        }
209      })
210
211      Button("close modal 1")
212        .margin(10)
213        .fontSize(20)
214        .onClick(() => {
215          this.isShow = false;
216        })
217    }
218    .width('100%')
219    .height('100%')
220    .justifyContent(FlexAlign.Center)
221    .scale({ x: this.isScale2, y: this.isScale2 })
222    .animation({ curve: curves.springMotion() })
223  }
224
225  build() {
226    Column() {
227      Button("transition modal 1")
228        .onClick(() => {
229          this.isShow = true
230        })
231        .fontSize(20)
232        .margin(10)
233        .bindContentCover(this.isShow, this.myBuilder(), {
234          modalTransition: ModalTransition.NONE,
235          backgroundColor: Color.Pink,
236          onWillAppear: () => {
237            console.log("BindContentCover onWillAppear.")
238          },
239          onAppear: () => {
240            console.log("BindContentCover onAppear.")
241          },
242          onWillDisappear: () => {
243            console.log("BindContentCover onWillDisappear.")
244          },
245          onDisappear: () => {
246            console.log("BindContentCover onDisappear.")
247          }
248        })
249    }
250    .justifyContent(FlexAlign.Center)
251    .backgroundColor("#ff49c8ab")
252    .width('100%')
253    .height('100%')
254    .scale({ x: this.isScale1, y: this.isScale1 })
255    .animation({ curve: curves.springMotion() })
256  }
257}
258```
259
260![zh-cn_full_screen_modal_none_2](figures/zh-cn_full_screen_modal_none_2.gif)
261
262### 示例3(上下切换转场)
263
264全屏模态上下切换转场。
265
266```ts
267// xxx.ets
268@Entry
269@Component
270struct ModalTransitionExample {
271  @State isShow: boolean = false
272  @State isShow2: boolean = false
273
274  @Builder
275  myBuilder2() {
276    Column() {
277      Button("close modal 2")
278        .margin(10)
279        .fontSize(20)
280        .onClick(() => {
281          this.isShow2 = false;
282        })
283    }
284    .width('100%')
285    .height('100%')
286  }
287
288  @Builder
289  myBuilder() {
290    Column() {
291      Button("transition modal 2")
292        .margin(10)
293        .fontSize(20)
294        .onClick(() => {
295          this.isShow2 = true;
296        }).bindContentCover(this.isShow2, this.myBuilder2(), {
297        modalTransition: ModalTransition.DEFAULT,
298        backgroundColor: Color.Gray,
299        onWillAppear: () => {
300          console.log("BindContentCover onWillAppear.")
301        },
302        onAppear: () => {
303          console.log("BindContentCover onAppear.")
304        },
305        onWillDisappear: () => {
306          console.log("BindContentCover onWillDisappear.")
307        },
308        onDisappear: () => {
309          console.log("BindContentCover onDisappear.")
310        }
311      })
312
313      Button("close modal 1")
314        .margin(10)
315        .fontSize(20)
316        .onClick(() => {
317          this.isShow = false;
318        })
319    }
320    .width('100%')
321    .height('100%')
322    .justifyContent(FlexAlign.Center)
323  }
324
325  build() {
326    Column() {
327      Button("transition modal 1")
328        .onClick(() => {
329          this.isShow = true
330        })
331        .fontSize(20)
332        .margin(10)
333        .bindContentCover(this.isShow, this.myBuilder(), {
334          modalTransition: ModalTransition.DEFAULT,
335          backgroundColor: Color.Pink,
336          onWillAppear: () => {
337            console.log("BindContentCover onWillAppear.")
338          },
339          onAppear: () => {
340            console.log("BindContentCover onAppear.")
341          },
342          onWillDisappear: () => {
343            console.log("BindContentCover onWillDisappear.")
344          },
345          onDisappear: () => {
346            console.log("BindContentCover onDisappear.")
347          }
348        })
349    }
350    .justifyContent(FlexAlign.Center)
351    .backgroundColor(Color.White)
352    .width('100%')
353    .height('100%')
354  }
355}
356```
357
358![zh-cn_full_screen_modal_default](figures/zh-cn_full_screen_modal_default.gif)
359
360### 示例4(透明度渐变转场)
361
362全屏模态透明度渐变转场。
363
364```ts
365// xxx.ets
366@Entry
367@Component
368struct ModalTransitionExample {
369  @State isShow: boolean = false
370  @State isShow2: boolean = false
371
372  @Builder
373  myBuilder2() {
374    Column() {
375      Button("close modal 2")
376        .margin(10)
377        .fontSize(20)
378        .onClick(() => {
379          this.isShow2 = false;
380        })
381    }
382    .width('100%')
383    .height('100%')
384    .justifyContent(FlexAlign.Center)
385  }
386
387  @Builder
388  myBuilder() {
389    Column() {
390      Button("transition modal 2")
391        .margin(10)
392        .fontSize(20)
393        .onClick(() => {
394          this.isShow2 = true;
395        }).bindContentCover(this.isShow2, this.myBuilder2(), {
396        modalTransition: ModalTransition.ALPHA,
397        backgroundColor: Color.Gray,
398        onWillAppear: () => {
399          console.log("BindContentCover onWillAppear.")
400        },
401        onAppear: () => {
402          console.log("BindContentCover onAppear.")
403        },
404        onWillDisappear: () => {
405          console.log("BindContentCover onWillDisappear.")
406        },
407        onDisappear: () => {
408          console.log("BindContentCover onDisappear.")
409        }
410      })
411
412      Button("close modal 1")
413        .margin(10)
414        .fontSize(20)
415        .onClick(() => {
416          this.isShow = false;
417        })
418    }
419    .width('100%')
420    .height('100%')
421    .justifyContent(FlexAlign.Center)
422  }
423
424  build() {
425    Column() {
426      Button("transition modal 1")
427        .onClick(() => {
428          this.isShow = true
429        })
430        .fontSize(20)
431        .margin(10)
432        .bindContentCover(this.isShow, this.myBuilder(), {
433          modalTransition: ModalTransition.ALPHA,
434          backgroundColor: Color.Pink,
435          onWillAppear: () => {
436            console.log("BindContentCover onWillAppear.")
437          },
438          onAppear: () => {
439            console.log("BindContentCover onAppear.")
440          },
441          onWillDisappear: () => {
442            console.log("BindContentCover onWillDisappear.")
443          },
444          onDisappear: () => {
445            console.log("BindContentCover onDisappear.")
446          }
447        })
448    }
449    .justifyContent(FlexAlign.Center)
450    .backgroundColor(Color.White)
451    .width('100%')
452    .height('100%')
453  }
454}
455```
456
457![zh-cn_full_screen_modal_alpha](figures/zh-cn_full_screen_modal_alpha.gif)
458
459### 示例5(设置不同效果的自定义转场)
460
461该示例主要演示全屏模态旋转,平移等自定义转场。
462
463```ts
464// xxx.ets
465@Entry
466@Component
467struct ModalTransitionExample {
468  @State isShow: boolean = false
469  @State isShow2: boolean = false
470
471  @Builder
472  myBuilder2() {
473    Column() {
474      Button("Close Modal 2")
475        .margin(10)
476        .fontSize(20)
477        .onClick(() => {
478          this.isShow2 = false;
479        })
480    }
481    .width('100%')
482    .height('100%')
483    .justifyContent(FlexAlign.Center)
484  }
485
486  @Builder
487  myBuilder() {
488    Column() {
489      Button("Transition Modal 2")
490        .margin(10)
491        .fontSize(20)
492        .onClick(() => {
493          this.isShow2 = true;
494        })
495        .bindContentCover(
496          this.isShow2,
497          this.myBuilder2(),
498          {
499            modalTransition: ModalTransition.DEFAULT,
500            backgroundColor: Color.Gray,
501            transition: TransitionEffect.SLIDE.animation({ duration: 5000, curve: Curve.LinearOutSlowIn }),
502            onWillDismiss: ((dismissContentCoverAction: DismissContentCoverAction) => {
503              if (dismissContentCoverAction.reason == DismissReason.PRESS_BACK) {
504                console.log("BindContentCover dismiss reason is back pressed")
505              }
506              dismissContentCoverAction.dismiss()
507            }),
508            onAppear: () => {
509              console.info("BindContentCover onAppear.")
510            },
511            onDisappear: () => {
512              this.isShow2 = false;
513              console.info("BindContentCover onDisappear.")
514            }
515          })
516
517      Button("Close Modal 1")
518        .margin(10)
519        .fontSize(20)
520        .onClick(() => {
521          this.isShow = false;
522        })
523    }
524    .width('100%')
525    .height('100%')
526    .justifyContent(FlexAlign.Center)
527  }
528
529  build() {
530    Column() {
531      Button("Transition Modal 1")
532        .onClick(() => {
533          this.isShow = true
534        })
535        .fontSize(20)
536        .margin(10)
537        .bindContentCover(
538          this.isShow,
539          this.myBuilder(),
540          {
541            modalTransition: ModalTransition.DEFAULT,
542            backgroundColor: Color.Pink,
543            transition: TransitionEffect.asymmetric(
544              TransitionEffect.OPACITY.animation({ duration: 1100 }).combine(
545                TransitionEffect.rotate({ z: 1, angle: 180 }).animation({ delay: 1000, duration: 1000 }))
546              ,
547              TransitionEffect.OPACITY.animation({ duration: 1200 }).combine(
548                TransitionEffect.rotate({ z: 1, angle: 180 }).animation({ duration: 1300 }))
549            ),
550            onWillDismiss: ((dismissContentCoverAction: DismissContentCoverAction) => {
551              if (dismissContentCoverAction.reason == DismissReason.PRESS_BACK) {
552                console.log("back pressed");
553              }
554              dismissContentCoverAction.dismiss()
555            }),
556            onAppear: () => {
557              console.log("BindContentCover onAppear.")
558            },
559            onDisappear: () => {
560              this.isShow = false;
561              console.log("BindContentCover onDisappear.")
562            }
563          })
564    }
565    .justifyContent(FlexAlign.Center)
566    .backgroundColor(Color.White)
567    .width('100%')
568    .height('100%')
569  }
570}
571```
572
573![zh-cn_full_screen_modal_alpha](figures/zh-cn_full_screen_modal_transition.gif)
574