ArkUI geometryTransition:卡片换位置,也别瞬移
【摘要】 今天我们要用 geometryTransition 做一个小场景:同一张卡片从列表里的缩略形态,展开成详情页的头图。 准备 页面文件是 entry/src/main/ets/pages/arkUI/motion/ArkUIGeometryTransitionDemo.ets。 我们只讲同一个元素在两种布局里的位置和尺寸
ArkUI geometryTransition:卡片换位置,也别瞬移
今天我们要用 geometryTransition 做一个小场景:同一张卡片从列表里的缩略形态,展开成详情页的头图。
准备
页面文件是 entry/src/main/ets/pages/arkUI/motion/ArkUIGeometryTransitionDemo.ets。
我们只讲同一个元素在两种布局里的位置和尺寸变化,不做列表联动,也不做真实详情页。
第一步:给同一个元素相同的 id
.geometryTransition('motion-hero-card')
收起布局里有一块蓝色小卡片,展开布局里也有一块蓝色大封面。它们不是同时存在,但都写了同一个 geometryTransition id。
第二步:切换布局时用 animateTo 包住状态
this.getUIContext().animateTo({ duration: 520, curve: Curve.EaseInOut }, () => {
this.expanded = !this.expanded;
})
这一步让布局切换有动画上下文。否则你只是换了一段 UI,用户看到的仍然可能是硬切。
运行后看什么
点“展开成详情形态”,小卡片会变成顶部封面。再点“回到列表形态”,它会回到列表里的位置。
如果你后面要做“列表卡片点开详情”的效果,可以先用这一页把几何转场跑通,再考虑业务数据和页面结构。
完整示例代码
@Entry
@Component
struct ArkUIGeometryTransitionDemo {
@State expanded: boolean = false;
private toggleLayout(): void {
this.getUIContext().animateTo({ duration: 520, curve: Curve.EaseInOut }, () => {
this.expanded = !this.expanded;
})
}
@Builder
sectionTitle(title: string, desc: string) {
Column({ space: 6 }) {
Text(title)
.fontSize(19)
.fontWeight(FontWeight.Bold)
.fontColor('#111827')
Text(desc)
.fontSize(13)
.fontColor('#6B7280')
.lineHeight(20)
}
.width('100%')
.alignItems(HorizontalAlign.Start)
}
build() {
Scroll() {
Column({ space: 22 }) {
Column({ space: 8 }) {
Text('ArkUI geometryTransition')
.fontSize(28)
.fontWeight(FontWeight.Bold)
.fontColor('#111827')
Text('卡片换位置,也别瞬移')
.fontSize(16)
.fontColor('#4B5563')
Text('这一页只做一个元素在两种布局里的变形。我们给它同一个 geometryTransition id,让 ArkUI 帮它接住位置和尺寸变化。')
.fontSize(14)
.fontColor('#6B7280')
.lineHeight(22)
}
.width('100%')
.alignItems(HorizontalAlign.Start)
this.sectionTitle('同一个元素,两个布局位置', '收起时它像列表里的小卡片,展开后变成详情头图。重点是 id 保持一致。')
Column({ space: 16 }) {
Button(this.expanded ? '回到列表形态' : '展开成详情形态')
.height(38)
.fontSize(14)
.fontColor('#FFFFFF')
.backgroundColor('#111827')
.borderRadius(19)
.padding({ left: 18, right: 18 })
.onClick(() => {
this.toggleLayout();
})
if (this.expanded) {
Column({ space: 14 }) {
Column({ space: 8 }) {
Text('详情封面')
.fontSize(22)
.fontWeight(FontWeight.Bold)
.fontColor('#FFFFFF')
Text('同一张卡片从列表位置变成顶部封面,过程不会突然跳。')
.fontSize(13)
.fontColor('#DBEAFE')
.lineHeight(20)
}
.width('100%')
.height(172)
.padding(20)
.borderRadius(22)
.backgroundColor('#2563EB')
.geometryTransition('motion-hero-card')
.alignItems(HorizontalAlign.Start)
.justifyContent(FlexAlign.End)
Text('下面可以继续放详情内容。这里先不展开业务,只看几何转场本身。')
.fontSize(14)
.fontColor('#475569')
.lineHeight(22)
}
.width('100%')
.alignItems(HorizontalAlign.Start)
} else {
Row({ space: 14 }) {
Column()
.width(76)
.height(76)
.borderRadius(18)
.backgroundColor('#2563EB')
.geometryTransition('motion-hero-card')
Column({ space: 6 }) {
Text('列表里的小卡片')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.fontColor('#111827')
Text('点按钮后,它会变成详情页头部区域。')
.fontSize(13)
.fontColor('#64748B')
.lineHeight(20)
}
.layoutWeight(1)
.alignItems(HorizontalAlign.Start)
}
.width('100%')
.padding(14)
.borderRadius(18)
.backgroundColor('#F8FAFC')
.border({ width: 1, color: '#E5E7EB' })
}
}
.width('100%')
.alignItems(HorizontalAlign.Start)
}
.width('100%')
.padding(24)
.alignItems(HorizontalAlign.Start)
}
.width('100%')
.height('100%')
.backgroundColor('#FFFFFF')
}
}
【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)