ArkUI 页面转场:页面切换别突然闪一下

举报
蓝瘦的蜕变 发表于 2026/11/08 21:13:26 2026/11/08
【摘要】 今天我们要做一个页面级转场:从入口页跳到目标页,再从目标页返回,让 Push 和 Pop 都有明确的进入、退出方向。 准备 这一篇有两个页面: entry/src/main/ets/pages/arkUI/motion/ArkUIPageTransitionDemo.ets entry/src/main/ets/pag

ArkUI 页面转场:页面切换别突然闪一下

今天我们要做一个页面级转场:从入口页跳到目标页,再从目标页返回,让 Push 和 Pop 都有明确的进入、退出方向。

准备

这一篇有两个页面:

  • entry/src/main/ets/pages/arkUI/motion/ArkUIPageTransitionDemo.ets
  • entry/src/main/ets/pages/arkUI/motion/ArkUIPageTransitionTargetDemo.ets

这里允许使用页面跳转和返回按钮,因为页面转场本身就离不开页面切换。其它动画页不需要这么做。

第一步:入口页负责打开目标页

this.getUIContext().getRouter().pushUrl({
  url: 'pages/arkUI/motion/ArkUIPageTransitionTargetDemo'
})

入口页只做一件事:打开目标页。我们不在这里塞业务参数,也不把页面转场和组件导航混在一起。

第二步:给页面配置进出场

PageTransitionEnter({ type: RouteType.Push, duration: 280, curve: Curve.EaseOut })
  .slide(SlideEffect.Right)
  .opacity(0)
PageTransitionExit({ type: RouteType.Push, duration: 220, curve: Curve.EaseIn })
  .slide(SlideEffect.Left)
  .opacity(0)

Push 时,目标页从右侧进入,当前页向左退出。Pop 时方向反过来。这样用户能感到页面关系,而不是突然换屏。

运行后看什么

点“打开目标页”,观察目标页从右侧进入。再点“返回入口页”,观察返回方向反过来。

如果你要做详情页、设置页、二级页,这种转场比硬切更容易让用户理解自己到了哪一层。

完整示例代码

入口页:

@Entry
@Component
struct ArkUIPageTransitionDemo {
  private openTargetPage(): void {
    this.getUIContext().getRouter().pushUrl({
      url: 'pages/arkUI/motion/ArkUIPageTransitionTargetDemo'
    })
  }

  build() {
    Column({ space: 22 }) {
      Column({ space: 8 }) {
        Text('ArkUI 页面转场')
          .fontSize(28)
          .fontWeight(FontWeight.Bold)
          .fontColor('#111827')
        Text('页面切换别突然闪一下')
          .fontSize(16)
          .fontColor('#4B5563')
        Text('这一页用 router 打开目标页,再用 PageTransitionEnter 和 PageTransitionExit 处理进出场。页面转场只放在页面级 Demo 里讲。')
          .fontSize(14)
          .fontColor('#6B7280')
          .lineHeight(22)
      }
      .width('100%')
      .alignItems(HorizontalAlign.Start)

      Column({ space: 12 }) {
        Text('入口页')
          .fontSize(20)
          .fontWeight(FontWeight.Bold)
          .fontColor('#111827')
        Text('点击按钮进入目标页。Push 时目标页从右侧进入,当前页向左退出;Pop 时方向反过来。')
          .fontSize(14)
          .fontColor('#475569')
          .lineHeight(22)

        Button('打开目标页')
          .height(40)
          .fontSize(14)
          .fontColor('#FFFFFF')
          .backgroundColor('#2563EB')
          .borderRadius(20)
          .padding({ left: 18, right: 18 })
          .onClick(() => {
            this.openTargetPage();
          })
      }
      .width('100%')
      .padding(18)
      .borderRadius(18)
      .backgroundColor('#EFF6FF')
      .border({ width: 1, color: '#BFDBFE' })
      .alignItems(HorizontalAlign.Start)
    }
    .width('100%')
    .height('100%')
    .padding(24)
    .backgroundColor('#FFFFFF')
    .justifyContent(FlexAlign.Start)
    .alignItems(HorizontalAlign.Start)
  }

  pageTransition() {
    PageTransitionEnter({ type: RouteType.Push, duration: 280, curve: Curve.EaseOut })
      .slide(SlideEffect.Right)
      .opacity(0)
    PageTransitionExit({ type: RouteType.Push, duration: 220, curve: Curve.EaseIn })
      .slide(SlideEffect.Left)
      .opacity(0)
    PageTransitionEnter({ type: RouteType.Pop, duration: 280, curve: Curve.EaseOut })
      .slide(SlideEffect.Left)
      .opacity(0)
    PageTransitionExit({ type: RouteType.Pop, duration: 220, curve: Curve.EaseIn })
      .slide(SlideEffect.Right)
      .opacity(0)
  }
}

目标页:

@Entry
@Component
struct ArkUIPageTransitionTargetDemo {
  private backToEntry(): void {
    this.getUIContext().getRouter().back()
  }

  build() {
    Column({ space: 22 }) {
      Column({ space: 8 }) {
        Text('目标页')
          .fontSize(28)
          .fontWeight(FontWeight.Bold)
          .fontColor('#111827')
        Text('转场要服务页面关系')
          .fontSize(16)
          .fontColor('#4B5563')
        Text('这一页只承接页面切换,不额外讲业务详情。返回时同样会触发 Pop 方向的页面转场。')
          .fontSize(14)
          .fontColor('#6B7280')
          .lineHeight(22)
      }
      .width('100%')
      .alignItems(HorizontalAlign.Start)

      Column({ space: 12 }) {
        Text('转场效果已经生效')
          .fontSize(20)
          .fontWeight(FontWeight.Bold)
          .fontColor('#FFFFFF')
        Text('PageTransitionEnter 处理进入,PageTransitionExit 处理退出。你可以把它理解成页面级别的进出场动画。')
          .fontSize(14)
          .fontColor('#DBEAFE')
          .lineHeight(22)

        Button('返回入口页')
          .height(40)
          .fontSize(14)
          .fontColor('#2563EB')
          .backgroundColor('#FFFFFF')
          .borderRadius(20)
          .padding({ left: 18, right: 18 })
          .onClick(() => {
            this.backToEntry();
          })
      }
      .width('100%')
      .padding(20)
      .borderRadius(20)
      .backgroundColor('#2563EB')
      .alignItems(HorizontalAlign.Start)
    }
    .width('100%')
    .height('100%')
    .padding(24)
    .backgroundColor('#FFFFFF')
    .justifyContent(FlexAlign.Start)
    .alignItems(HorizontalAlign.Start)
  }

  pageTransition() {
    PageTransitionEnter({ type: RouteType.Push, duration: 280, curve: Curve.EaseOut })
      .slide(SlideEffect.Right)
      .opacity(0)
    PageTransitionExit({ type: RouteType.Push, duration: 220, curve: Curve.EaseIn })
      .slide(SlideEffect.Left)
      .opacity(0)
    PageTransitionEnter({ type: RouteType.Pop, duration: 280, curve: Curve.EaseOut })
      .slide(SlideEffect.Left)
      .opacity(0)
    PageTransitionExit({ type: RouteType.Pop, duration: 220, curve: Curve.EaseIn })
      .slide(SlideEffect.Right)
      .opacity(0)
  }
}
【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。