1# 页面转场动画 (不推荐) 2<!--Kit: ArkUI--> 3<!--Subsystem: ArkUI--> 4<!--Owner: @CCFFWW--> 5<!--Designer: @yangfan229--> 6<!--Tester: @lxl007--> 7<!--Adviser: @HelloCrease--> 8 9为了实现更好的转场效果,推荐使用[组件导航(Navigation)](arkts-navigation-navigation.md)和[模态转场](arkts-modal-transition.md)。 10 11两个页面间发生跳转,一个页面消失,另一个页面出现,这时可以配置各自页面的页面转场参数实现自定义的页面转场效果。[页面转场](../reference/apis-arkui/arkui-ts/ts-page-transition-animation.md)效果写在pageTransition函数中,通过[PageTransitionEnter](../reference/apis-arkui/arkui-ts/ts-page-transition-animation.md#pagetransitionenter)和[PageTransitionExit](../reference/apis-arkui/arkui-ts/ts-page-transition-animation.md#pagetransitionexit)指定页面进入和退出的动画效果。 12pageTransition的函数为: 13 14```ts 15pageTransition() { 16 PageTransitionEnter() 17 PageTransitionExit() 18} 19``` 20 21 22PageTransitionEnter的接口为: 23 24```ts 25PageTransitionEnter({type?: RouteType,duration?: number,curve?: Curve | string,delay?: number}) 26``` 27 28 29PageTransitionExit的接口为: 30 31```ts 32PageTransitionExit({type?: RouteType,duration?: number,curve?: Curve | string,delay?: number}) 33``` 34 35 36上述接口定义了PageTransitionEnter和PageTransitionExit组件,可通过slide、translate、scale、opacity属性定义不同的页面转场效果。对于PageTransitionEnter而言,这些效果表示入场时起点值,对于PageTransitionExit而言,这些效果表示退场的终点值,这一点与组件转场transition配置方法类似。此外,PageTransitionEnter提供了onEnter接口进行自定义页面入场动画的回调,PageTransitionExit提供了onExit接口进行自定义页面退场动画的回调。 37 38 39上述接口中的参数type,表示路由生效的类型,这一点开发者容易混淆其含义。页面转场的两个页面,必定有一个页面退出,一个页面进入。如果通过[pushUrl](../reference/apis-arkui/arkts-apis-uicontext-router.md#pushurl)操作从页面A跳转到页面B,则页面A退出,做页面退场动画,页面B进入,做页面入场动画。如果通过[back](../reference/apis-arkui/arkts-apis-uicontext-router.md#back)操作从页面B返回到页面A,则页面B退出,做页面退场动画,页面A进入,做页面入场动画。即页面的PageTransitionEnter既可能是由于新增页面(push,入栈)引起的新页面的入场动画,也可能是由于页面返回(back,或pop,出栈)引起的页面栈中老页面的入场动画,为了能区分这两种形式的入场动画,提供了type参数,这样开发者能完全定义所有类型的页面转场效果。 40 41 42## type配置为RouteType.None 43 44type为RouteType.None表示对页面栈的push、pop操作均生效,type的默认值为RouteType.None。 45 46 47```ts 48// page A 49pageTransition() { 50 // 定义页面进入时的效果,从左侧滑入,时长为1200ms,无论页面栈发生push还是pop操作均可生效 51 PageTransitionEnter({ type: RouteType.None, duration: 1200 }) 52 .slide(SlideEffect.Left) 53 // 定义页面退出时的效果,向左侧滑出,时长为1000ms,无论页面栈发生push还是pop操作均可生效 54 PageTransitionExit({ type: RouteType.None, duration: 1000 }) 55 .slide(SlideEffect.Left) 56} 57``` 58 59```ts 60// page B 61pageTransition() { 62 // 定义页面进入时的效果,从右侧滑入,时长为1000ms,无论页面栈发生push还是pop操作均可生效 63 PageTransitionEnter({ type: RouteType.None, duration: 1000 }) 64 .slide(SlideEffect.Right) 65 // 定义页面退出时的效果,向右侧滑出,时长为1200ms,无论页面栈发生push还是pop操作均可生效 66 PageTransitionExit({ type: RouteType.None, duration: 1200 }) 67 .slide(SlideEffect.Right) 68} 69``` 70 71 72假设页面跳转配置为多实例模式,即页面栈中允许存在重复的页面。可能会有4种场景,对应的页面转场效果如下表。 73 74 75| 路由操作 | 页面A转场效果 | 页面B转场效果 | 76| ---------------------------- | ---------------------------------- | ---------------------------------- | 77| pushUrl,从页面A跳转到新增的页面B | 页面退出,PageTransitionExit生效,向左侧滑出屏幕 | 页面进入,PageTransitionEnter生效,从右侧滑入屏幕 | 78| back,从页面B返回到页面A | 页面进入,PageTransitionEnter生效,从左侧滑入屏幕 | 页面退出,PageTransitionExit生效,向右侧滑出屏幕 | 79| pushUrl,从页面B跳转到新增的页面A | 页面进入,PageTransitionEnter生效,从左侧滑入屏幕 | 页面退出,PageTransitionExit生效,向右侧滑出屏幕 | 80| back,从页面A返回到页面B | 页面退出,PageTransitionExit生效,向左侧滑出屏幕 | 页面进入,PageTransitionEnter生效,从右侧滑入屏幕 | 81 82 83如果希望pushUrl进入的页面总是从右侧滑入,back时退出的页面总是从右侧滑出,则上表中的第3、4种情况不满足要求,那么需要完整的定义4个页面转场效果。 84 85 86## type配置为RouteType.Push或RouteType.Pop 87 88type为RouteType.Push表示仅对页面栈的push操作生效,type为RouteType.Pop表示仅对页面栈的pop操作生效。 89 90 91```ts 92// page A 93pageTransition() { 94 // 定义页面进入时的效果,从右侧滑入,时长为1200ms,页面栈发生push操作时该效果才生效 95 PageTransitionEnter({ type: RouteType.Push, duration: 1200 }) 96 .slide(SlideEffect.Right) 97 // 定义页面进入时的效果,从左侧滑入,时长为1200ms,页面栈发生pop操作时该效果才生效 98 PageTransitionEnter({ type: RouteType.Pop, duration: 1200 }) 99 .slide(SlideEffect.Left) 100 // 定义页面退出时的效果,向左侧滑出,时长为1000ms,页面栈发生push操作时该效果才生效 101 PageTransitionExit({ type: RouteType.Push, duration: 1000 }) 102 .slide(SlideEffect.Left) 103 // 定义页面退出时的效果,向右侧滑出,时长为1000ms,页面栈发生pop操作时该效果才生效 104 PageTransitionExit({ type: RouteType.Pop, duration: 1000 }) 105 .slide(SlideEffect.Right) 106} 107``` 108 109```ts 110// page B 111pageTransition() { 112 // 定义页面进入时的效果,从右侧滑入,时长为1000ms,页面栈发生push操作时该效果才生效 113 PageTransitionEnter({ type: RouteType.Push, duration: 1000 }) 114 .slide(SlideEffect.Right) 115 // 定义页面进入时的效果,从左侧滑入,时长为1000ms,页面栈发生pop操作时该效果才生效 116 PageTransitionEnter({ type: RouteType.Pop, duration: 1000 }) 117 .slide(SlideEffect.Left) 118 // 定义页面退出时的效果,向左侧滑出,时长为1200ms,页面栈发生push操作时该效果才生效 119 PageTransitionExit({ type: RouteType.Push, duration: 1200 }) 120 .slide(SlideEffect.Left) 121 // 定义页面退出时的效果,向右侧滑出,时长为1200ms,页面栈发生pop操作时该效果才生效 122 PageTransitionExit({ type: RouteType.Pop, duration: 1200 }) 123 .slide(SlideEffect.Right) 124} 125``` 126 127 128以上代码则完整的定义了所有可能的页面转场样式。假设页面跳转配置为多实例模式,即页面栈中允许存在重复的页面。可能会有4种场景,对应的页面转场效果如下表。 129 130 131| 路由操作 | 页面A转场效果 | 页面B转场效果 | 132| ---------------------------- | ---------------------------------------- | ---------------------------------------- | 133| pushUrl,从页面A跳转到新增的页面B | 页面退出,PageTransitionExit且type为RouteType.Push的转场样式生效,向左侧滑出屏幕 | 页面进入,PageTransitionEnter且type为RouteType.Push的转场样式生效,从右侧滑入屏幕 | 134| back,从页面B返回到页面A | 页面进入,PageTransitionEnter且type为RouteType.Pop的转场样式生效,从左侧滑入屏幕 | 页面退出,PageTransitionExit且type为RouteType.Pop的转场样式生效,向右侧滑出屏幕 | 135| pushUrl,从页面B跳转到新增的页面A | 页面进入,PageTransitionEnter且type为RouteType.Push的转场样式生效,从右侧滑入屏幕 | 页面退出,PageTransitionExit且type为RouteType.Push的转场样式生效,向左侧滑出屏幕 | 136| back,从页面A返回到页面B | 页面退出,PageTransitionExit且type为RouteType.Pop的转场样式生效,向右侧滑出屏幕 | 页面进入,PageTransitionEnter且type为RouteType.Pop的转场样式生效,从左侧滑入屏幕 | 137 138 139>**说明:** 140> 141> 1. 由于每个页面的页面转场样式都可由开发者独立配置,而页面转场涉及到两个页面,开发者应考虑两个页面的页面转场效果的衔接,如时长尽量保持一致。 142> 143> 2. 如果没有定义匹配的页面转场样式,则该页面使用系统默认的页面转场样式。 144 145 146## 禁用某页面的页面转场 147 148 149```ts 150pageTransition() { 151 PageTransitionEnter({ type: RouteType.None, duration: 0 }) 152 PageTransitionExit({ type: RouteType.None, duration: 0 }) 153} 154``` 155 156 157通过设置页面转场的时长为0,可使该页面无页面转场动画。 158 159 160## 场景示例 161 162下面介绍了利用[pushUrl](../reference/apis-arkui/arkts-apis-uicontext-router.md#pushurl)跳转能力定义了所有的四种页面转场样式的页面转场动画示例。 163 164```ts 165// PageTransitionSrc1 166@Entry 167@Component 168struct PageTransitionSrc1 { 169 build() { 170 Column() { 171 Image($r('app.media.mountain')) 172 .width('90%') 173 .height('80%') 174 .objectFit(ImageFit.Fill) 175 .syncLoad(true) // 同步加载图片,使页面出现时图片已经加载完成 176 .margin(30) 177 178 Row({ space: 10 }) { 179 Button("pushUrl") 180 .onClick(() => { 181 // 路由到下一个页面,push操作 182 this.getUIContext().getRouter().pushUrl({ url: 'pages/myTest/pageTransitionDst1' }); 183 }) 184 Button("back") 185 .onClick(() => { 186 // 返回到上一页面,相当于pop操作 187 this.getUIContext().getRouter().back(); 188 }) 189 }.justifyContent(FlexAlign.Center) 190 } 191 .width("100%").height("100%") 192 .alignItems(HorizontalAlign.Center) 193 } 194 195 pageTransition() { 196 // 定义页面进入时的效果,从右侧滑入,时长为1000ms,页面栈发生push操作时该效果才生效 197 PageTransitionEnter({ type: RouteType.Push, duration: 1000 }) 198 .slide(SlideEffect.Right) 199 // 定义页面进入时的效果,从左侧滑入,时长为1000ms,页面栈发生pop操作时该效果才生效 200 PageTransitionEnter({ type: RouteType.Pop, duration: 1000 }) 201 .slide(SlideEffect.Left) 202 // 定义页面退出时的效果,向左侧滑出,时长为1000ms,页面栈发生push操作时该效果才生效 203 PageTransitionExit({ type: RouteType.Push, duration: 1000 }) 204 .slide(SlideEffect.Left) 205 // 定义页面退出时的效果,向右侧滑出,时长为1000ms,页面栈发生pop操作时该效果才生效 206 PageTransitionExit({ type: RouteType.Pop, duration: 1000 }) 207 .slide(SlideEffect.Right) 208 } 209} 210``` 211 212 213 214 215```ts 216// PageTransitionDst1 217@Entry 218@Component 219struct PageTransitionDst1 { 220 build() { 221 Column() { 222 Image($r('app.media.forest')) 223 .width('90%') 224 .height('80%') 225 .objectFit(ImageFit.Fill) 226 .syncLoad(true) // 同步加载图片,使页面出现时图片已经加载完成 227 .margin(30) 228 229 Row({ space: 10 }) { 230 Button("pushUrl") 231 .onClick(() => { 232 // 路由到下一页面,push操作 233 this.getUIContext().getRouter().pushUrl({ url: 'pages/myTest/pageTransitionSrc1' }); 234 }) 235 Button("back") 236 .onClick(() => { 237 // 返回到上一页面,相当于pop操作 238 this.getUIContext().getRouter().back(); 239 }) 240 }.justifyContent(FlexAlign.Center) 241 } 242 .width("100%").height("100%") 243 .alignItems(HorizontalAlign.Center) 244 } 245 246 pageTransition() { 247 // 定义页面进入时的效果,从右侧滑入,时长为1000ms,页面栈发生push操作时该效果才生效 248 PageTransitionEnter({ type: RouteType.Push, duration: 1000 }) 249 .slide(SlideEffect.Right) 250 // 定义页面进入时的效果,从左侧滑入,时长为1000ms,页面栈发生pop操作时该效果才生效 251 PageTransitionEnter({ type: RouteType.Pop, duration: 1000 }) 252 .slide(SlideEffect.Left) 253 // 定义页面退出时的效果,向左侧滑出,时长为1000ms,页面栈发生push操作时该效果才生效 254 PageTransitionExit({ type: RouteType.Push, duration: 1000 }) 255 .slide(SlideEffect.Left) 256 // 定义页面退出时的效果,向右侧滑出,时长为1000ms,页面栈发生pop操作时该效果才生效 257 PageTransitionExit({ type: RouteType.Pop, duration: 1000 }) 258 .slide(SlideEffect.Right) 259 } 260} 261``` 262 263 264 265 266 267 268下面介绍使用了type为None的页面转场动画示例。 269 270 271 272```ts 273// PageTransitionSrc2 274@Entry 275@Component 276struct PageTransitionSrc2 { 277 build() { 278 Column() { 279 Image($r('app.media.mountain')) 280 .width('90%') 281 .height('80%') 282 .objectFit(ImageFit.Fill) 283 .syncLoad(true) // 同步加载图片,使页面出现时图片已经加载完成 284 .margin(30) 285 286 Row({ space: 10 }) { 287 Button("pushUrl") 288 .onClick(() => { 289 // 路由到下一页面,push操作 290 this.getUIContext().getRouter().pushUrl({ url: 'pages/myTest/pageTransitionDst2' }); 291 }) 292 Button("back") 293 .onClick(() => { 294 // 返回到上一页面,相当于pop操作 295 this.getUIContext().getRouter().back(); 296 }) 297 }.justifyContent(FlexAlign.Center) 298 } 299 .width("100%").height("100%") 300 .alignItems(HorizontalAlign.Center) 301 } 302 303 pageTransition() { 304 // 定义页面进入时的效果,从左侧滑入,时长为1000ms,无论页面栈发生push还是pop操作均可生效 305 PageTransitionEnter({ duration: 1000 }) 306 .slide(SlideEffect.Left) 307 // 定义页面退出时的效果,相对于正常页面位置x方向平移100vp,y方向平移100vp,透明度变为0,时长为1200ms,无论页面栈发生push还是pop操作均可生效 308 PageTransitionExit({ duration: 1200 }) 309 .translate({ x: 100.0, y: 100.0 }) 310 .opacity(0) 311 } 312} 313``` 314 315 316 317```ts 318// PageTransitionDst2 319@Entry 320@Component 321struct PageTransitionDst2 { 322 build() { 323 Column() { 324 Image($r('app.media.forest')) 325 .width('90%') 326 .height('80%') 327 .objectFit(ImageFit.Fill) 328 .syncLoad(true) // 同步加载图片,使页面出现时图片已经加载完成 329 .margin(30) 330 331 Row({ space: 10 }) { 332 Button("pushUrl") 333 .onClick(() => { 334 // 路由到下一页面,push操作 335 this.getUIContext().getRouter().pushUrl({ url: 'pages/myTest/pageTransitionSrc2' }); 336 }) 337 Button("back") 338 .onClick(() => { 339 // 返回到上一页面,相当于pop操作 340 this.getUIContext().getRouter().back(); 341 }) 342 }.justifyContent(FlexAlign.Center) 343 } 344 .width("100%").height("100%") 345 .alignItems(HorizontalAlign.Center) 346 } 347 348 pageTransition() { 349 // 定义页面进入时的效果,从左侧滑入,时长为1200ms,无论页面栈发生push还是pop操作均可生效 350 PageTransitionEnter({ duration: 1200 }) 351 .slide(SlideEffect.Left) 352 // 定义页面退出时的效果,相对于正常页面位置x方向平移100vp,y方向平移100vp,透明度变为0,时长为1000ms,无论页面栈发生push还是pop操作均可生效 353 PageTransitionExit({ duration: 1000 }) 354 .translate({ x: 100.0, y: 100.0 }) 355 .opacity(0) 356 } 357} 358``` 359 360 361 362 363