【鸿蒙基于API 13实战开发】—— ArkUI 组件:旋转屏动画增强&&页面转场动画
如果通过router.back操作从页面B返回到页面A,则页面B退出,做页面退场动画,页面A进入,做页面入场动画。即页面的PageTransitionEnter既可能是由于新增页面(push,入栈)引起的新页面的入场动画,也可能是由于页面返回(back,或pop,出栈)引起的页面栈中老页面的入场动画,为了能区分这两种形式的入场动画,提供了type参数,这样开发者能完全定义所有类型的页面转场效果。两
🚀往期学习笔录🔰:
🔰 鸿蒙应用开发与鸿蒙系统开发哪个更有前景?
🔰 嵌入式开发适不适合做鸿蒙南向开发?看完这篇你就了解了~
🔰对于大前端开发来说,转鸿蒙开发究竟是福还是祸?
🔰 鸿蒙岗位需求突增!移动端、PC端、IoT到底该怎么选?
🔰 记录一场鸿蒙开发岗位面试经历~
🔰 持续更新中……
旋转屏动画增强
在原旋转屏动画基础上,可配置渐隐和渐现的转场效果。
完整的代码示例和效果如下。
// xx.ets
import { display } from '@kit.ArkUI';
@Entry
@Component
struct rotation {
@StorageLink('orientation') myOrientation: display.Orientation = display.Orientation.PORTRAIT;
build() {
Stack() {
if (this.myOrientation == display.Orientation.PORTRAIT || this.myOrientation == display.Orientation.PORTRAIT_INVERTED) {
Image($r('app.media.sky'))
.size({ width: 100, height: 100 })
.id('image1')
} else {
Image($r('app.media.tree'))
.position({ x: 0, y: 0 })
.size({ width: 200, height: 200 })
.id('image2')
}
}
.backgroundColor(Color.White)
.size({ width: '100%', height: '100%' })
}
}
需要在EntryAbility.ets文件的onWindowStageCreate方法中添加处理逻辑以获取屏幕的显示方向
onWindowStageCreate(windowStage: window.WindowStage): void {
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
let mainWindow: window.Window;
try {
mainWindow = windowStage.getMainWindowSync();
let displayClass: display.Display = display.getDefaultDisplaySync();
AppStorage.setOrCreate('orientation', displayClass.orientation);
// 监听窗口的windowsSizeChange事件,旋转屏时会触发该事件
mainWindow.on('windowSizeChange', (data) => {
console.info('Succeeded in enabling the listener for window size changes. Data: ' + JSON.stringify(data));
let displayClass: display.Display | null = null;
try {
displayClass = display.getDefaultDisplaySync();
console.info('display orientation is ' + JSON.stringify(displayClass.orientation));
// 获取屏幕的显示方向
AppStorage.set('orientation', displayClass.orientation);
} catch {
return;
}
})
} catch {
hilog.info(0x0000, 'testTag', '%{public}s', 'error');
return;
}
windowStage.loadContent('pages/Index', (err) => {
if (err.code) {
hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
return;
}
hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.');
});
}
需要在项目的 module.json5 文件中的 abilities 列表里添加 “orientation”,指定为 “auto_rotation”
"orientation": "auto_rotation",

页面转场动画 (不推荐)
为了实现更好的转场效果,推荐使用 导航转场 和 模态转场 。
两个页面间发生跳转,一个页面消失,另一个页面出现,这时可以配置各自页面的页面转场参数实现自定义的页面转场效果。 页面转场 效果写在pageTransition函数中,通过 PageTransitionEnter 和 PageTransitionExit 指定页面进入和退出的动画效果。
pageTransition的函数为:
pageTransition() {
PageTransitionEnter()
PageTransitionExit()
}
PageTransitionEnter的接口为:
PageTransitionEnter({type?: RouteType,duration?: number,curve?: Curve | string,delay?: number})
PageTransitionExit的接口为:
PageTransitionExit({type?: RouteType,duration?: number,curve?: Curve | string,delay?: number})
上述接口定义了PageTransitionEnter和PageTransitionExit组件,可通过slide、translate、scale、opacity属性定义不同的页面转场效果。对于PageTransitionEnter而言,这些效果表示入场时起点值,对于PageTransitionExit而言,这些效果表示退场的终点值,这一点与组件转场transition配置方法类似。此外,PageTransitionEnter提供了onEnter接口进行自定义页面入场动画的回调,PageTransitionExit提供了onExit接口进行自定义页面退场动画的回调。
上述接口中的参数type,表示路由生效的类型,这一点开发者容易混淆其含义。页面转场的两个页面,必定有一个页面退出,一个页面进入。如果通过router.pushUrl操作从页面A跳转到页面B,则页面A退出,做页面退场动画,页面B进入,做页面入场动画。如果通过router.back操作从页面B返回到页面A,则页面B退出,做页面退场动画,页面A进入,做页面入场动画。即页面的PageTransitionEnter既可能是由于新增页面(push,入栈)引起的新页面的入场动画,也可能是由于页面返回(back,或pop,出栈)引起的页面栈中老页面的入场动画,为了能区分这两种形式的入场动画,提供了type参数,这样开发者能完全定义所有类型的页面转场效果。
type配置为RouteType.None
type为RouteType.None表示对页面栈的push、pop操作均生效,type的默认值为RouteType.None。
// page A
pageTransition() {
// 定义页面进入时的效果,从左侧滑入,时长为1200ms,无论页面栈发生push还是pop操作均可生效
PageTransitionEnter({ type: RouteType.None, duration: 1200 })
.slide(SlideEffect.Left)
// 定义页面退出时的效果,向左侧滑出,时长为1000ms,无论页面栈发生push还是pop操作均可生效
PageTransitionExit({ type: RouteType.None, duration: 1000 })
.slide(SlideEffect.Left)
}
// page B
pageTransition() {
// 定义页面进入时的效果,从右侧滑入,时长为1000ms,无论页面栈发生push还是pop操作均可生效
PageTransitionEnter({ type: RouteType.None, duration: 1000 })
.slide(SlideEffect.Right)
// 定义页面退出时的效果,向右侧滑出,时长为1200ms,无论页面栈发生push还是pop操作均可生效
PageTransitionExit({ type: RouteType.None, duration: 1200 })
.slide(SlideEffect.Right)
}
假设页面跳转配置为多实例模式,即页面栈中允许存在重复的页面。可能会有4种场景,对应的页面转场效果如下表。
| 路由操作 | 页面A转场效果 | 页面B转场效果 |
|---|---|---|
| router.pushUrl,从页面A跳转到新增的页面B | 页面退出,PageTransitionExit生效,向左侧滑出屏幕 | 页面进入,PageTransitionEnter生效,从右侧滑入屏幕 |
| router.back,从页面B返回到页面A | 页面进入,PageTransitionEnter生效,从左侧滑入屏幕 | 页面退出,PageTransitionExit生效,向右侧滑出屏幕 |
| router.pushUrl,从页面B跳转到新增的页面A | 页面进入,PageTransitionEnter生效,从左侧滑入屏幕 | 页面退出,PageTransitionExit生效,向右侧滑出屏幕 |
| router.back,从页面A返回到页面B | 页面退出,PageTransitionExit生效,向左侧滑出屏幕 | 页面进入,PageTransitionEnter生效,从右侧滑入屏幕 |
如果希望pushUrl进入的页面总是从右侧滑入,back时退出的页面总是从右侧滑出,则上表中的第3、4种情况不满足要求,那么需要完整的定义4个页面转场效果。
type配置为RouteType.Push或RouteType.Pop
type为RouteType.Push表示仅对页面栈的push操作生效,type为RouteType.Pop表示仅对页面栈的pop操作生效。
// page A
pageTransition() {
// 定义页面进入时的效果,从右侧滑入,时长为1200ms,页面栈发生push操作时该效果才生效
PageTransitionEnter({ type: RouteType.Push, duration: 1200 })
.slide(SlideEffect.Right)
// 定义页面进入时的效果,从左侧滑入,时长为1200ms,页面栈发生pop操作时该效果才生效
PageTransitionEnter({ type: RouteType.Pop, duration: 1200 })
.slide(SlideEffect.Left)
// 定义页面退出时的效果,向左侧滑出,时长为1000ms,页面栈发生push操作时该效果才生效
PageTransitionExit({ type: RouteType.Push, duration: 1000 })
.slide(SlideEffect.Left)
// 定义页面退出时的效果,向右侧滑出,时长为1000ms,页面栈发生pop操作时该效果才生效
PageTransitionExit({ type: RouteType.Pop, duration: 1000 })
.slide(SlideEffect.Right)
}
// page B
pageTransition() {
// 定义页面进入时的效果,从右侧滑入,时长为1000ms,页面栈发生push操作时该效果才生效
PageTransitionEnter({ type: RouteType.Push, duration: 1000 })
.slide(SlideEffect.Right)
// 定义页面进入时的效果,从左侧滑入,时长为1000ms,页面栈发生pop操作时该效果才生效
PageTransitionEnter({ type: RouteType.Pop, duration: 1000 })
.slide(SlideEffect.Left)
// 定义页面退出时的效果,向左侧滑出,时长为1200ms,页面栈发生push操作时该效果才生效
PageTransitionExit({ type: RouteType.Push, duration: 1200 })
.slide(SlideEffect.Left)
// 定义页面退出时的效果,向右侧滑出,时长为1200ms,页面栈发生pop操作时该效果才生效
PageTransitionExit({ type: RouteType.Pop, duration: 1200 })
.slide(SlideEffect.Right)
}
以上代码则完整的定义了所有可能的页面转场样式。假设页面跳转配置为多实例模式,即页面栈中允许存在重复的页面。可能会有4种场景,对应的页面转场效果如下表。
| 路由操作 | 页面A转场效果 | 页面B转场效果 |
|---|---|---|
| router.pushUrl,从页面A跳转到新增的页面B | 页面退出,PageTransitionExit且type为RouteType.Push的转场样式生效,向左侧滑出屏幕 | 页面进入,PageTransitionEnter且type为RouteType.Push的转场样式生效,从右侧滑入屏幕 |
| router.back,从页面B返回到页面A | 页面进入,PageTransitionEnter且type为RouteType.Pop的转场样式生效,从左侧滑入屏幕 | 页面退出,PageTransitionExit且type为RouteType.Pop的转场样式生效,向右侧滑出屏幕 |
| router.pushUrl,从页面B跳转到新增的页面A | 页面进入,PageTransitionEnter且type为RouteType.Push的转场样式生效,从右侧滑入屏幕 | 页面退出,PageTransitionExit且type为RouteType.Push的转场样式生效,向左侧滑出屏幕 |
| router.back,从页面A返回到页面B | 页面退出,PageTransitionExit且type为RouteType.Pop的转场样式生效,向右侧滑出屏幕 | 页面进入,PageTransitionEnter且type为RouteType.Pop的转场样式生效,从左侧滑入屏幕 |
说明
- 由于每个页面的页面转场样式都可由开发者独立配置,而页面转场涉及到两个页面,开发者应考虑两个页面的页面转场效果的衔接,如时长尽量保持一致。
- 如果没有定义匹配的页面转场样式,则该页面使用系统默认的页面转场样式。
禁用某页面的页面转场
pageTransition() {
PageTransitionEnter({ type: RouteType.None, duration: 0 })
PageTransitionExit({ type: RouteType.None, duration: 0 })
}
通过设置页面转场的时长为0,可使该页面无页面转场动画。
场景示例
下面介绍了利用 router.pushUrl 跳转能力定义了所有的四种页面转场样式的页面转场动画示例。
// PageTransitionSrc1
@Entry
@Component
struct PageTransitionSrc1 {
build() {
Column() {
Image($r('app.media.mountain'))
.width('90%')
.height('80%')
.objectFit(ImageFit.Fill)
.syncLoad(true) // 同步加载图片,使页面出现时图片已经加载完成
.margin(30)
Row({ space: 10 }) {
Button("pushUrl")
.onClick(() => {
// 路由到下一个页面,push操作
this.getUIContext().getRouter().pushUrl({ url: 'pages/myTest/pageTransitionDst1' });
})
Button("back")
.onClick(() => {
// 返回到上一页面,相当于pop操作
this.getUIContext().getRouter().back();
})
}.justifyContent(FlexAlign.Center)
}
.width("100%").height("100%")
.alignItems(HorizontalAlign.Center)
}
pageTransition() {
// 定义页面进入时的效果,从右侧滑入,时长为1000ms,页面栈发生push操作时该效果才生效
PageTransitionEnter({ type: RouteType.Push, duration: 1000 })
.slide(SlideEffect.Right)
// 定义页面进入时的效果,从左侧滑入,时长为1000ms,页面栈发生pop操作时该效果才生效
PageTransitionEnter({ type: RouteType.Pop, duration: 1000 })
.slide(SlideEffect.Left)
// 定义页面退出时的效果,向左侧滑出,时长为1000ms,页面栈发生push操作时该效果才生效
PageTransitionExit({ type: RouteType.Push, duration: 1000 })
.slide(SlideEffect.Left)
// 定义页面退出时的效果,向右侧滑出,时长为1000ms,页面栈发生pop操作时该效果才生效
PageTransitionExit({ type: RouteType.Pop, duration: 1000 })
.slide(SlideEffect.Right)
}
}
<pre class="ts prettyprint linenums hljs language-typescript" data-highlighted="yes" style="bo
// PageTransitionDst1
@Entry
@Component
struct PageTransitionDst1 {
build() {
Column() {
Image($r('app.media.forest'))
.width('90%')
.height('80%')
.objectFit(ImageFit.Fill)
.syncLoad(true) // 同步加载图片,使页面出现时图片已经加载完成
.margin(30)
Row({ space: 10 }) {
Button("pushUrl")
.onClick(() => {
// 路由到下一页面,push操作
this.getUIContext().getRouter().pushUrl({ url: 'pages/myTest/pageTransitionSrc1' });
})
Button("back")
.onClick(() => {
// 返回到上一页面,相当于pop操作
this.getUIContext().getRouter().back();
})
}.justifyContent(FlexAlign.Center)
}
.width("100%").height("100%")
.alignItems(HorizontalAlign.Center)
}
pageTransition() {
// 定义页面进入时的效果,从右侧滑入,时长为1000ms,页面栈发生push操作时该效果才生效
PageTransitionEnter({ type: RouteType.Push, duration: 1000 })
.slide(SlideEffect.Right)
// 定义页面进入时的效果,从左侧滑入,时长为1000ms,页面栈发生pop操作时该效果才生效
PageTransitionEnter({ type: RouteType.Pop, duration: 1000 })
.slide(SlideEffect.Left)
// 定义页面退出时的效果,向左侧滑出,时长为1000ms,页面栈发生push操作时该效果才生效
PageTransitionExit({ type: RouteType.Push, duration: 1000 })
.slide(SlideEffect.Left)
// 定义页面退出时的效果,向右侧滑出,时长为1000ms,页面栈发生pop操作时该效果才生效
PageTransitionExit({ type: RouteType.Pop, duration: 1000 })
.slide(SlideEffect.Right)
}
}

下面介绍使用了type为None的页面转场动画示例。
// PageTransitionSrc2
@Entry
@Component
struct PageTransitionSrc2 {
build() {
Column() {
Image($r('app.media.mountain'))
.width('90%')
.height('80%')
.objectFit(ImageFit.Fill)
.syncLoad(true) // 同步加载图片,使页面出现时图片已经加载完成
.margin(30)
Row({ space: 10 }) {
Button("pushUrl")
.onClick(() => {
// 路由到下一页面,push操作
this.getUIContext().getRouter().pushUrl({ url: 'pages/myTest/pageTransitionDst2' });
})
Button("back")
.onClick(() => {
// 返回到上一页面,相当于pop操作
this.getUIContext().getRouter().back();
})
}.justifyContent(FlexAlign.Center)
}
.width("100%").height("100%")
.alignItems(HorizontalAlign.Center)
}
pageTransition() {
// 定义页面进入时的效果,从左侧滑入,时长为1000ms,无论页面栈发生push还是pop操作均可生效
PageTransitionEnter({ duration: 1000 })
.slide(SlideEffect.Left)
// 定义页面退出时的效果,相对于正常页面位置x方向平移100vp,y方向平移100vp,透明度变为0,时长为1200ms,无论页面栈发生push还是pop操作均可生效
PageTransitionExit({ duration: 1200 })
.translate({ x: 100.0, y: 100.0 })
.opacity(0)
}
}
// PageTransitionDst2
@Entry
@Component
struct PageTransitionDst2 {
build() {
Column() {
Image($r('app.media.forest'))
.width('90%')
.height('80%')
.objectFit(ImageFit.Fill)
.syncLoad(true) // 同步加载图片,使页面出现时图片已经加载完成
.margin(30)
Row({ space: 10 }) {
Button("pushUrl")
.onClick(() => {
// 路由到下一页面,push操作
this.getUIContext().getRouter().pushUrl({ url: 'pages/myTest/pageTransitionSrc2' });
})
Button("back")
.onClick(() => {
// 返回到上一页面,相当于pop操作
this.getUIContext().getRouter().back();
})
}.justifyContent(FlexAlign.Center)
}
.width("100%").height("100%")
.alignItems(HorizontalAlign.Center)
}
pageTransition() {
// 定义页面进入时的效果,从左侧滑入,时长为1200ms,无论页面栈发生push还是pop操作均可生效
PageTransitionEnter({ duration: 1200 })
.slide(SlideEffect.Left)
// 定义页面退出时的效果,相对于正常页面位置x方向平移100vp,y方向平移100vp,透明度变为0,时长为1000ms,无论页面栈发生push还是pop操作均可生效
PageTransitionExit({ duration: 1000 })
.translate({ x: 100.0, y: 100.0 })
.opacity(0)
}
}

更多推荐



所有评论(0)