HarmonyOS 鸿蒙Next共享转场

HarmonyOS 鸿蒙Next共享转场

这个怎么写都触发不了,是不是因为最外层的Navigation的问题下面是代码

import { IndexBuilder } from './Index/Index'

@Entry
@Component
struct Main {
  @Provide('pageStack') pageStack: NavPathStack = new NavPathStack()

  build() {
    Navigation(this.pageStack) {
      IndexBuilder()
    }
  }
}
import CardComponent from "../../components/CardComponent/CardComponent"

@Builder
export function IndexBuilder() {
  Index()
}

@Preview
@Component
export struct Index {
  @Consume('pageStack') pageStack: NavPathStack

  build() {
    NavDestination() {
      Scroll() {
        Row({ space: 18 }) {
          CardComponent()
        }
      }.scrollable(ScrollDirection.Horizontal).scrollBar(BarState.Off)
    }.hideBackButton(true).title("首页")
  }
}
@Builder
export function CardComponentBuilder(){
  CardComponent()
}
@Component
export default  struct CardComponent {
  @Prop image: string = 'https://tailwindcss.com/plus-assets/img/ecommerce-images/home-page-03-featured-category.jpg'
  @Prop title: string = '123'
  @Prop subtitle: string = '123'
  @Consume('pageStack') pageStack: NavPathStack

  build() {
    Column() {
      Stack() {
        Image(this.image)
          .width('100%')
          .height('100%')
          .objectFit(ImageFit.Cover)
          .sharedTransition('sharedImage', { duration: 800, curve: Curve.Linear, delay: 100 })
          .onClick(() => {
            this.pageStack.pushPath({
              name:"Detailedplaylist"
            })
          })
        Column({ space: 8 }) {
          Text("歌单名").fontSize(20).fontWeight(FontWeight.Bold)
          Text("其他文字").fontSize(16)
        }
        .width("100%")
        .height("25%")
        .align(Alignment.Center)
        .justifyContent(FlexAlign.Center)
        .backgroundBlurStyle(BlurStyle.BACKGROUND_THIN)
      }
      .width(200)
      .height(320)
      .borderRadius(24)
      .clip(true)
      .shadow({ radius: 8, color: '#00000026', offsetY: 4 })
      .align(Alignment.Bottom)
    }
  }
}
@Builder
export function DetailedplaylistBuilder(){
  Detailedplaylist()
}

@Component
export default   struct Detailedplaylist{
  image: string = 'https://tailwindcss.com/plus-assets/img/ecommerce-images/home-page-03-featured-category.jpg'
  build() {
    NavDestination() {
      Stack() {
        Image(this.image)
          .width('100%')
          .height('50%')
          .sharedTransition('sharedImage', { duration: 800, curve: Curve.Linear, delay: 100 })
      }
    }
  }
}

更多关于HarmonyOS 鸿蒙Next共享转场的实战教程也可以访问 https://www.itying.com/category-93-b0.html

4 回复

【背景知识】

共享元素转场:可以通过设置组件的sharedTransition属性将该元素标记为共享元素并设置对应的共享元素转场动效。sharedTransition仅发生在页面路由(router)跳转时。

【问题定位】

根据实例代码分析sharedTransition未使用animateTo触发动效。

【分析结论】

未使用animateTo触发动效:sharedTransition必须通过animateTo包裹导航操作才能触发动画,直接通过pushPath或pushUrl跳转时,缺乏动画上下文。

【修改建议】

使用animateTo包裹跳转逻辑:修改点击事件的导航代码,通过动画上下文触发转场:

.onClick(() => {
  animateTo({ duration: 800 }, () => {
    this.pageStack.pushPath({ name: "Detailedplaylist" });
  });
})

修改后的代码如下:

// 源页面(CardComponent)
Image(this.image)
  .sharedTransition('sharedImage', { duration: 800, curve: Curve.Linear })
  .onClick(() => {
    animateTo({ duration: 800 }, () => {
      this.pageStack.pushPath({ name: "Detailedplaylist" });
    });
  });

// 目标页面(Detailedplaylist)
Image(this.detailImage)
  .sharedTransition('sharedImage', { duration: 800, curve: Curve.Linear })

【总结】

共享元素转场触发失败可能的原因有:

  • 未在目标页面绑定相同id的共享元素:共享转场需要源页面与目标页面同时定义相同的sharedTransition id。若目标页面的对应组件未设置相同id,动画将无法关联。
  • 未使用animateTo触发动效:sharedTransition必须通过animateTo包裹导航操作才能触发动画。直接通过pushPath或pushUrl跳转时,缺乏动画上下文。
  • Navigation容器层级影响:Navigation组件可能通过独立的页面栈管理视图层级,若共享元素未正确置于同一动效作用域内,会导致转场失效。

更多关于HarmonyOS 鸿蒙Next共享转场的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


楼主,照着这个写,有效果了吗?

鸿蒙Next的共享转场是ArkUI提供的页面间动画效果,基于共享元素实现。开发者使用sharedTransition属性定义共享组件,通过matchedKeyword关联相同标识符的组件。转场时系统自动匹配并执行平滑过渡动画,支持位置、大小、形状等属性的渐变。需在pageTransition中配置共享转场参数,包括durationcurve等。此功能仅适用于声明式开发范式,需确保前后页面共享元素的组件类型一致。

从代码来看,共享转场无法触发的主要原因是Navigation组件的使用方式问题。在HarmonyOS Next中,共享转场需要在两个页面间建立关联,但当前代码结构存在以下关键问题:

  1. 共享转场要求两个页面必须位于同一个Navigation组件内,但你的Detail页面没有通过Navigation进行跳转,而是直接使用了NavDestination

  2. 在CardComponent中虽然设置了sharedTransition,但在目标页面Detailedplaylist中缺少对应的共享元素声明

建议修改方案:

  1. 确保两个页面使用相同的Navigation堆栈:
// Main.ts
@Entry
@Component
struct Main {
  @Provide('pageStack') pageStack: NavPathStack = new NavPathStack()

  build() {
    Navigation(this.pageStack) {
      IndexBuilder()
      DetailedplaylistBuilder() // 添加目标页面
    }
  }
}
  1. 在Detailedplaylist组件中确保使用相同的sharedTransition ID:
Image(this.image)
  .sharedTransition('sharedImage', { 
    duration: 800, 
    curve: Curve.Linear, 
    delay: 100 
  })
  1. 确保跳转时使用Navigation的push方法:
this.pageStack.pushPath({
  name: "Detailedplaylist"
})

这种结构才能确保共享转场动画正常触发。

回到顶部