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