
前言
页面转场动画是提升应用交互体验的关键手段。HarmonyOS 提供了两种动画机制:transition(组件转场动画)和 animateTo(显式动画)。两者的适用场景和实现方式不同,但可以配合使用来实现流畅的页面切换效果。本文以小事记(xiaoshiji_ohos_app) 的 EventDetailPage.ets 为分析对象,深入解析页面转场动画的实现。
本文参考 HarmonyOS 官方文档:arkts-transition-overview.md 和 arkts-animation-transition.md。
一、transition 组件转场动画
1.1 transition 的基本用法
transition 用于组件出现和消失时的动画效果:
// transition 的基本用法
@Entry
@Component
struct EventDetailPage {
@State isVisible: boolean = false;
build() {
Column() {
if (this.isVisible) {
Text('事件详情')
.transition(TransitionEffect.OPACITY) // 透明度过渡
.transition(TransitionEffect.SLIDE) // 滑动过渡
}
}
.onClick(() => {
this.isVisible = !this.isVisible;
})
}
}
1.2 TransitionEffect 类型
| 类型 | 说明 | 适用场景 |
|---|---|---|
OPACITY | 透明度过渡 | 淡入淡出效果 |
SLIDE | 滑动过渡 | 页面从边缘滑入 |
SCALE | 缩放过渡 | 放大/缩小效果 |
MOVE | 移动过渡 | 指定方向的移动 |
ROTATE | 旋转过渡 | 旋转效果 |
1.3 组合使用
// 组合使用多种过渡效果
this.cardTransition = TransitionEffect.OPACITY
.combine(TransitionEffect.SLIDE)
.combine(TransitionEffect.SCALE);
二、animateTo 显式动画
2.1 animateTo 的基本用法
// animateTo 显式动画
import { animateTo } from '@kit.ArkUI';
@Entry
@Component
struct MemoryVideoPage {
@State isPlaying: boolean = false;
@State currentProgress: number = 0;
@Builder
buildPlayButton() {
Circle()
.width(72)
.height(72)
.fill('#FFFFFF30')
.border({ width: 2, color: Color.White })
Text('▶')
.fontSize(28)
.fontColor(Color.White)
.margin({ top: -52 })
.onClick(() => {
animateTo({ duration: 300, curve: Curve.EaseInOut }, () => {
this.isPlaying = !this.isPlaying;
});
})
}
}
2.2 animateTo 的配置参数
| 参数 | 类型 | 说明 | 默认值 |
|---|---|---|---|
duration | number | 动画持续时长(ms) | 300 |
curve | Curve | 动画曲线 | Curve.Ease |
delay | number | 延迟执行时间(ms) | 0 |
iterations | number | 动画重复次数 | 1 |
onFinish | () => void | 动画完成回调 | — |
三、页面转场动画的完整实现
3.1 列表页到详情页的转场
// 首页事件卡片的点击转场
@Entry
@Component
struct HomePage {
private stack: NavPathStack = new NavPathStack();
@Builder
buildEventItem(event: LifeEvent) {
Column() {
Text(event.title)
.fontSize(16)
.fontWeight(FontWeight.Bold)
Text(event.content)
.fontSize(13)
.fontColor('#6B7280')
}
.padding(12)
.backgroundColor(Color.White)
.borderRadius(12)
.onClick(() => {
// 使用 animateTo 添加转场动画
animateTo({ duration: 300, curve: Curve.EaseInOut }, () => {
this.stack.pushPathByName('EventDetailPage', { event });
});
})
}
}
3.2 详情页的进入动画
// EventDetailPage.ets — 页面进入动画
@Entry
@Component
struct EventDetailPage {
@State isContentVisible: boolean = false;
aboutToAppear(): void {
// 延迟显示内容,实现逐层进入效果
setTimeout(() => {
animateTo({ duration: 400, curve: Curve.EaseOut }, () => {
this.isContentVisible = true;
});
}, 100);
}
build() {
Scroll() {
Column() {
// 顶部渐变区域
Column()
.width('100%')
.height(240)
.linearGradient({ angle: 135, colors: [['#7B68EE', 0.0], ['#DDA0DD', 1.0]] })
.borderRadius({ bottomLeft: 20, bottomRight: 20 })
.transition(TransitionEffect.OPACITY) // 透明度过渡
// 内容区域
if (this.isContentVisible) {
Column() {
Text(this.event.title)
.fontSize(22)
.fontWeight(FontWeight.Bold)
Text(this.event.content)
.fontSize(15)
.fontColor('#6B7280')
}
.transition(TransitionEffect.OPACITY
.combine(TransitionEffect.SLIDE))
}
}
}
}
}
四、动画曲线
4.1 内置动画曲线
| 曲线 | 说明 | 适用场景 |
|---|---|---|
Curve.Linear | 线性 | 匀速运动 |
Curve.Ease | 缓入缓出 | 默认,适用于大多数场景 |
Curve.EaseIn | 缓入 | 加速进入 |
Curve.EaseOut | 缓出 | 减速退出 |
Curve.EaseInOut | 缓入缓出 | 平滑过渡 |
Curve.FastOutSlowIn | 快入慢出 | 自然感 |
4.2 自定义贝塞尔曲线
// 自定义动画曲线
import { Curve } from '@kit.ArkUI';
const customCurve = Curve.cubicBezier(0.42, 0.0, 0.58, 1.0);
animateTo({ duration: 300, curve: customCurve }, () => {
this.isVisible = true;
});
五、常见问题
5.1 动画不执行
问题:transition 或 animateTo 没有生效。
可能原因:
- 状态变量未使用
@State装饰 - 动画参数配置错误
- 组件未正确包裹在条件渲染中
// ✅ 正确:状态变量必须使用 @State
@State isVisible: boolean = false;
// ❌ 错误:普通变量不会触发动画
isVisible: boolean = false;
5.2 动画卡顿
问题:动画执行时出现卡顿。
解决方案:
- 减少动画的复杂度
- 使用
scale替代width/height动画 - 避免在动画中触发布局变化
八、拓展阅读
本节汇总了与本文主题相关的扩展阅读材料,帮助读者深入理解相关技术细节。
8.1 官方文档
- 开发者指南:HarmonyOS 应用开发概述
- API 参考:ArkTS API 参考
8.2 相关技术文章
- 性能优化最佳实践
- 常见问题排查指南
8.3 社区资源
十、最佳实践与优化建议
在实际开发中,合理运用上述技术可以显著提升应用的性能和用户体验。以下是几个关键的最佳实践建议:
10.1 性能优化要点
| 优化方向 | 具体措施 | 预期效果 |
|---|---|---|
| 渲染性能 | 减少不必要的组件重建 | 提升帧率 |
| 内存管理 | 及时释放不再使用的资源 | 降低内存占用 |
| 响应速度 | 避免在主线程执行耗时操作 | 提升交互流畅度 |
10.2 推荐实践步骤
按照以下步骤进行优化:
- 使用 DevEco Studio 的 Profiler 工具分析当前性能瓶颈
- 针对识别出的热点进行针对性优化
- 通过单元测试和集成测试验证优化效果
- 在真机环境下进行回归测试
10.3 代码示例
// 推荐的最佳实践示例
@Component
export struct OptimizedComponent {
// 使用 @State 管理最小粒度的状态
@State private isActive: boolean = false;
build() {
Column() {
Text(this.isActive ? '激活' : '未激活')
.fontSize(16)
}
.onClick(() => {
// 使用 animateTo 实现平滑过渡
animateTo({ duration: 300 }, () => {
this.isActive = !this.isActive;
});
});
}
}
最佳实践提示:在编写代码时,始终遵循 ArkUI 的性能优化原则,避免在 build() 方法中执行复杂计算或频繁的状态更新。
总结
本文深入解析了页面转场动画的实现。核心要点如下:
- transition 组件转场:适用于组件出现和消失的场景,支持
OPACITY、SLIDE、SCALE等效果 - animateTo 显式动画:适用于状态变化驱动的动画,支持
duration、curve、delay等参数配置 - 动画曲线:内置多种曲线,支持自定义贝塞尔曲线
- 组合动画:
transition和animateTo可以配合使用,实现丰富的转场效果
如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!
九、完整示例代码
9.1 完整组件实现
以下是一个完整的组件实现示例,展示了本文介绍的各个技术点的综合运用:
import { Component, State, Prop } from '@kit.ArkUI';
@Component
export struct DemoComponent {
@Prop title: string = '';
@State count: number = 0;
build() {
Column({ space: 12 }) {
// 标题区域
Text(this.title)
.fontSize(18)
.fontWeight(FontWeight.Bold)
.fontColor('#1A1A2E')
.width('100%')
// 内容区域
Text(`当前计数: ${this.count}`)
.fontSize(14)
.fontColor('#6B7280')
// 交互按钮
Button('点击增加')
.width(120)
.height(40)
.backgroundColor('#7B68EE')
.borderRadius(20)
.fontColor(Color.White)
.onClick(() => {
this.count++;
})
}
.width('100%')
.padding(16)
.backgroundColor(Color.White)
.borderRadius(12)
.shadow({ radius: 4, color: '#00000008', offsetX: 0, offsetY: 2 })
}
}
9.2 使用方式
在页面中引入并使用该组件:
@Entry
@Component
struct Index {
build() {
Column() {
DemoComponent({ title: '示例组件' })
}
.width('100%')
.height('100%')
.backgroundColor('#F8F9FA')
}
}
9.3 代码说明
- 组件封装:使用
@Component装饰器定义可复用的组件 - 状态管理:使用
@State管理组件内部状态 - 参数传递:使用
@Prop接收外部传入的参数 - 事件处理:使用
onClick处理用户交互 - 样式优化:使用
borderRadius、shadow等属性美化 UI
相关资源:
- 官方文档 - 开发者指南:HarmonyOS 应用开发
- 官方文档 - ArkUI 组件参考:ArkUI 组件
- 官方文档 - API 参考:API 参考
- 官方文档 - 状态管理:状态管理概述
- 官方文档 - 动画:动画概述
- 官方文档 - 网络管理:网络管理
- 官方文档 - 数据管理:数据管理
- 开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

320

被折叠的 条评论
为什么被折叠?



