从基础到实战:鸿蒙 ArkUI 转场动画开发指南

鸿蒙动画概述

在移动应用开发中,动画是提升用户体验的核心手段之一。流畅、自然的动画效果能让应用界面更具生动性和交互感,有效降低用户操作的生硬感,增强应用的易用性与吸引力。

ArkUI 提供了丰富的动画接口,核心包括属性动画、转场动画、粒子动画等,其核心原理是:驱动组件属性值按照预设的动画参数,从起始值逐步过渡到终点值。尽管属性值的变化本质上具有一定离散性,但借助人眼的视觉暂留效应,最终呈现出连续流畅的动画效果。

UI 界面的每一次更新称为一个动画帧,对应一次屏幕刷新,而帧率(FPS,Frames Per Second)是衡量动画流畅度的关键指标——帧率越高,动画越顺滑,用户视觉体验越好。

动画接口分类与作用

动画类型 作用 特点
属性动画 最基础的动画类型,由系统驱动属性逐帧变化,生成连续动画效果 除自定义属性动画外,应用侧无需感知动画过程
转场动画 为组件的出现、消失提供过渡效果 部分接口内置固定动画曲线,不支持开发者自定义,以保证动画一致性
粒子动画 实现粒子特效 丰富视觉效果,提升交互体验
组件动画 组件自带默认动效(如 List 滑动动效) 同时部分组件支持自定义动效,降低开发成本
帧动画 系统提供动画过程中的插值结果,由开发者每帧修改属性值生成动画 支持暂停操作,但性能表现稍弱

在鸿蒙众多动画 API 中,转场动画是专门用于组件出现和消失时的过渡效果,与属性动画相辅相成,共同构建流畅的用户体验。

鸿蒙转场动画介绍

转场动画用于对即将出现或消失的组件施加动画效果,始终显示的组件应使用属性动画。转场动画旨在简化开发者对组件消失节点的管理,如果使用属性动画实现组件转场,开发者需在动画结束回调中手动删除组件节点。此外,动画结束前已删除的节点可能重新出现,因此需在回调中增加对节点状态的判断逻辑。

转场动画分类

转场动画主要分为以下几类:

  1. 出现/消失转场:对新增、消失的控件实现动画效果,是通用的基础转场效果。

  2. 模态转场:新的界面覆盖在旧的界面之上的动画,旧的界面不消失,新的界面出现,如弹框就是典型的模态转场动画。

  3. 共享元素转场 (一镜到底):共享元素转场是一种界面切换时对相同或者相似的元素做的一种位置和大小匹配的过渡动画效果。

  4. 旋转屏动画:旋转屏动画主要分为布局切换的旋转屏动画和透明度变化的旋转屏动画,旨在实现屏幕显示方向变化时的自然过渡。

  5. 页面转场动画:页面的路由转场方式,可以通过在pageTransition函数中自定义页面入场和页面退场的转场动效。为了实现更好的转场效果,推荐使用导航转场和模态转场。

  6. 导航转场:页面的路由转场方式,对应一个界面消失,另外一个界面出现的动画效果,如设置应用一级菜单切换到二级界面。

限于文章篇幅,本文仅介绍出现/消失转场动画

转场动画的核心概念

  1. 过渡效果:定义组件出现或消失时的动画效果,如移动、缩放、旋转、透明度变化等。

  2. 过渡方向:指定组件出现或消失的方向,如从左、右、上、下等方向进入或退出。

  3. 动画参数:控制转场动画的持续时间、曲线类型、延迟时间等。

  4. 对称/非对称转场:对称转场指组件出现和消失时使用相同的动画效果,非对称转场指组件出现和消失时使用不同的动画效果。

鸿蒙出现/消失转场动画的实现方式

1 TransitionEffect对象介绍

TransitionEffect 是转场动画的核心对象,提供了多种转场效果的创建方法,包括:

转场效果 说明 动画
IDENTITY 禁用转场效果
OPACITY 默认的转场效果,透明度转场 出现时透明度从0到1,消失时透明度从1到0
SLIDE 滑动转场效果 出现时从窗口左侧滑入,消失时从窗口右侧滑出
translate 通过设置组件平移创建转场效果 出现时,平移参数的值从translate接口设置的值变化为默认值0,消失时从默认值0变化为translate接口设置的值
rotate 通过设置组件旋转创建转场效果 出现时,旋转参数的值从rotate接口设置的值变化为默认值0,消失时从默认值0变化为rotate接口设置的值
opacity 通过设置透明度参数创建转场效果 出现时,透明度参数的值从opacity设置的值变化为透明度默认值1,消失时从透明度默认值1变化为opacity设置的值
move 通过TransitionEdge创建从窗口哪条边缘出来的效果 出现时从TransitionEdge方向滑入,消失时滑出到TransitionEdge方向
asymmetric 通过此方法组合非对称的出现消失转场效果 出现时采用appear设置的TransitionEffect出现效果,消失时采用disappear设置的TransitionEffect消失效果
combine 组合其他TransitionEffect 组合其他TransitionEffect,一起生效
animation 定义转场效果的动画参数 调用顺序是从上往下,上面TransitionEffect的animation也会作用到下面TransitionEffect

2 基本转场动画实现

通过 transition 方法为组件添加转场动画效果,适用于组件的出现和消失场景。

import { TransitionEffect, TransitionEdge, Curve } from '@kit.ArkUI';

@Entry
@Component
struct BasicTransitionDemo {
  @State showComponent: boolean = false;

  build() {
    Column({
      space: 20
    }) {
      Button('显示/隐藏组件')
        .width(200)
        .height(60)
        .onClick(() => {
          this.showComponent = !this.showComponent;
        })

      if (this.showComponent) {
        Column()
          .width(200)
          .height(200)
          .backgroundColor(Color.Blue)
          .justifyContent(FlexAlign.Center)
          // 使用move效果,从右侧进入,左侧退出
          .transition(
            TransitionEffect.move(TransitionEdge.END)
              .animation({ duration: 500, curve: Curve.Ease })
          )
      }
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

3 非对称转场动画实现

通过 asymmetric 方法实现组件出现和消失时使用不同的动画效果。

import { TransitionEffect, TransitionEdge, Curve } from '@kit.ArkUI';

@Entry
@Component
struct AsymmetricTransitionDemo {
  @State showComponent: boolean = false;

  build() {
    Column({
      space: 20
    }) {
      Button('显示/隐藏组件')
        .width(200)
        .height(60)
        .onClick(() => {
          this.showComponent = !this.showComponent;
        })

      if (this.showComponent) {
        Column()
          .width(200)
          .height(200)
          .backgroundColor(Color.Blue)
          .justifyContent(FlexAlign.Center)
          // 使用asymmetric方法,实现非对称转场效果
          .transition(
            TransitionEffect.asymmetric(
              // 组件出现时的动画:从下方进入,透明度从0到1
              TransitionEffect.move(TransitionEdge.BOTTOM)
                .animation({ duration: 500, curve: Curve.EaseOut })
                .combine(TransitionEffect.opacity(0)),
              // 组件消失时的动画:从上方退出,透明度从1到0
              TransitionEffect.move(TransitionEdge.TOP)
                .animation({ duration: 500, curve: Curve.EaseIn })
                .combine(TransitionEffect.opacity(0))
            )
          )
      }
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

4 组合转场效果

通过 combine 方法组合多种转场效果,实现更复杂的动画效果。

import { curves } from '@kit.ArkUI';

@Entry
@Component
struct TransitionEffectDemo {
  @State isPresent: boolean = false;
  // 第一步:创建TransitionEffect
  private effect: TransitionEffect =
    // 创建默认透明度转场效果,并指定了springMotion(0.6, 0.8)曲线
    TransitionEffect.OPACITY.animation({
      curve: curves.springMotion(0.6, 0.8)
    })// 通过combine方法,这里的动画参数会跟随上面的TransitionEffect,也就是springMotion(0.6, 0.8)
      .combine(TransitionEffect.scale({
        x: 0,
        y: 0
      }))// 添加旋转转场效果,这里的动画参数会跟随上面带animation的TransitionEffect,也就是springMotion(0.6, 0.8)
      .combine(TransitionEffect.rotate({ angle: 90 }))// 添加平移转场效果,这里的动画参数使用指定的springMotion()
      .combine(TransitionEffect.translate({ y: 150 })
        .animation({ curve: curves.springMotion() }))// 添加move转场效果,这里的动画参数会跟随上面的TransitionEffect,也就是springMotion()
      .combine(TransitionEffect.move(TransitionEdge.END));

  build() {
    Stack() {
      if (this.isPresent) {
        Column() {
          Text('ArkUI')
            .fontWeight(FontWeight.Bold)
            .fontSize(20)
            .fontColor(Color.White)
        }
        .justifyContent(FlexAlign.Center)
        .width(150)
        .height(150)
        .borderRadius(10)
        .backgroundColor(0xf56c6c)
        // 第二步:将转场效果通过transition接口设置到组件
        .transition(this.effect)
      }

      // 边框
      Column()
        .width(155)
        .height(155)
        .border({
          width: 5,
          radius: 10,
          color: Color.Black
        })

      // 第三步:新增或者删除组件触发转场,控制新增或者删除组件
      Button('Click')
        .margin({ top: 320 })
        .onClick(() => {
          this.isPresent = !this.isPresent;
        })
    }
    .width('100%')
    .height('60%')
  }
}

在这里插入图片描述

5 多个组件的转场动画

对多个组件添加转场效果时,可以在animation动画参数中配置不同的delay值,实现组件渐次出现消失的效果。

const ITEM_COUNTS = 9;
const ITEM_COLOR = '#ED6F21';
const INTERVAL = 30;
const DURATION = 300;

@Entry
@Component
struct Index1 {
  @State isGridShow: boolean = false;
  private dataArray: number[] = new Array(ITEM_COUNTS);

  aboutToAppear(): void {
    for (let i = 0; i < ITEM_COUNTS; i++) {
      this.dataArray[i] = i;
    }
  }

  build() {
    Stack() {
      if (this.isGridShow) {
        Grid() {
          ForEach(this.dataArray, (item: number, index: number) => {
            GridItem() {
              Stack() {
                Text((item + 1).toString())
              }
              .size({ width: 50, height: 50 })
              .backgroundColor(ITEM_COLOR)
              .transition(TransitionEffect.OPACITY
                .combine(TransitionEffect.scale({ x: 0.5, y: 0.5 }))// 对每个方格的转场添加delay,实现组件的渐次出现消失效果
                .animation({ duration: DURATION, curve: Curve.Friction, delay: INTERVAL * index }))
              .borderRadius(10)
            }
            // 消失时,如果不对方格的所有父控件添加转场效果,则方格的消失转场不会生效
            // 此处让方格的父控件在出现消失转场时一直以0.99的透明度显示,使得方格的转场效果不受影响
            .transition(TransitionEffect.opacity(0.99))
          }, (item: number) => item.toString())
        }
        .columnsTemplate('1fr 1fr 1fr')
        .rowsGap(15)
        .columnsGap(15)
        .size({ width: 180, height: 180 })
        // 消失时,如果不对方格的所有父控件添加转场效果,则方格的消失转场不会生效
        // 此处让父控件在出现消失转场时一直以0.99的透明度显示,使得方格的转场效果不受影响
        .transition(TransitionEffect.opacity(0.99))
      }
    }
    .size({ width: '100%', height: '100%' })
    .onClick(() => {
      this.getUIContext()?.animateTo({
        duration: DURATION + INTERVAL * (ITEM_COUNTS - 1),
        curve: Curve.Friction
      }, () => {
        this.isGridShow = !this.isGridShow;
      })
    })
  }
}

在这里插入图片描述

项目实战:喵屿应用中的转场动画

喵屿是一款宠物管理类应用,为提升用户体验,应用中广泛运用转场动画,实现了生动的交互效果和视觉反馈。以下结合具体代码示例,讲解转场动画在实际项目中的落地方式、优化策略及最终效果。

1. 应用中的转场动画实现

喵屿应用的转场动画设计遵循“简洁、自然、贴合场景”的原则,重点运用 transition 方法实现组件的出现和消失动画,提升用户交互体验。

1.1 日记页面转场动画

DiaryView.ets 中,通过symmetric组合非对称的出现消失转场效果,增强页面的动态效果:

// 空状态转场动画
Column() {
  Image($r("[resource].media.empty_heart"))
    .width(80)
    .height(100)
    .draggable(false)

  Text($r('[resource].string.no_item'))
    .fontSize(15)
    .fontColor($r("[resource].color.gray_2"))
}
.transition(
  TransitionEffect.asymmetric(
    // 出现时的动画:从右侧进入,同时透明度变化
    TransitionEffect.move(TransitionEdge.END)
      .animation({
        duration: duration,
        delay: delay,
        curve: Curve.Ease
      })
      .combine(TransitionEffect.opacity(opacity)),
    // 消失时的动画:从左侧退出,同时透明度变化
    TransitionEffect.move(TransitionEdge.START)
      .animation({
        duration: duration,
        delay: delay,
        curve: Curve.Ease
      })
      .combine(TransitionEffect.opacity(opacity))
  )
)

// 列表转场动画
Column() {
  CatList({
    bgColor: this.bgColor,
    allTitle: '所有',
    onClickBack: (item?: BaseInfo) => {
      this.curCat = item?.UUID ?? ''
      this.catFilter()
    }
  })
  .padding({ left: 16, right: 16 })
}
.width('100%')
.height(120)
.padding({
  top: $r('app.integer.calendar_switch_size_four'),
  bottom: $r('app.integer.calendar_switch_size_four'),
})
.transition(
  // 出现时的动画:从右侧进入,同时透明度变化
  TransitionEffect.move(TransitionEdge.END)
    .animation({ duration: duration, curve: Curve.Ease })
    .combine(TransitionEffect.opacity(opacity))
)
1.2 设置页面转场动画

Settings.ets 中,通过combine接口组合其他TransitionEffect。实现了设置项平移叠加透明度变化的出现和消失转场动画:

// 设置项转场动画
ListItem() {
  this.listItem(item)
}
.padding({ left: 16, right: 16 })
.width(CommonConstants.FULL_SIZE)
.opacity(this.isShow ? 1 : 0)
.translate({ x: this.isShow ? 0 : 100 })
.transition(
  // 出现时的动画:从右侧进入,同时透明度变化
  TransitionEffect.move(TransitionEdge.END)
    .animation({ duration: 500, delay: index * 50, curve: Curve.EaseOut })
    .combine(TransitionEffect.opacity(0))
)

在这里插入图片描述

2. 转场动画优化策略

在实际项目开发中,转场动画的流畅性直接影响用户体验,若动画卡顿、延迟,会降低应用的专业度。喵屿应用在转场动画开发中,结合鸿蒙系统特性,采用了以下优化策略,兼顾动画效果与性能。

  1. 合理设置动画时长:根据转场场景的复杂度,设置适配的时长——简单转场(如列表项出现)设置 300~500ms,复杂转场(如页面切换)设置 500~800ms,避免过长导致等待感,过短导致过渡突兀。

  2. 精准选择动画曲线:结合场景选择合适的曲线,如列表项入场用 Curve.EaseOut 实现平滑过渡,页面切换用 Curve.EaseInOut 实现自然过渡,让动画更贴合真实物理规律,提升自然感。

  3. 避免过度动画:核心交互场景(如页面切换、模态弹窗)使用转场动画增强反馈,非核心场景(如普通列表刷新)不添加转场动画,避免视觉疲劳和性能消耗。

  4. 巧用动画延迟:在列表、网格等多元素场景中,为不同元素设置递增的动画延迟,创造层次感和流动感,同时避免多元素同时动画导致的性能压力。

  5. 结合震动反馈:转场动画触发时,搭配轻微的震动反馈(如弹窗出现、页面切换),增强用户的触觉交互,让动画反馈更立体。

  6. 区分转场类型:根据组件的出现和消失方式,选择合适的转场类型,如从右侧进入的组件用 TransitionEdge.END,从左侧退出的组件用 TransitionEdge.START,保持动画的一致性。

  7. 控制转场触发条件:在某些场景下(如滑动操作),需要暂时关闭转场动画,避免动画与用户操作冲突,提升用户体验。

总结

鸿蒙转场动画是专门用于组件出现和消失时的过渡效果,与属性动画相辅相成,共同构建流畅的用户体验。其核心优势在于:

  • 简化开发:转场动画自动管理组件的出现和消失,无需开发者手动处理节点管理,降低开发复杂度。

  • 效果丰富:支持多种转场类型和动画效果,如移动、缩放、旋转、透明度变化等,满足不同场景的需求。

  • 性能优秀:鸿蒙系统对转场动画进行了优化,保证了动画的流畅性和性能,即使在复杂场景下也能保持良好的用户体验。

  • 扩展性强:可以与属性动画、粒子动画等结合使用,实现更复杂的动画效果,为应用增添更多创意空间。

核心要点总结

  1. 转场动画的核心是“为组件的出现和消失提供过渡效果”,适用于临时显示或隐藏的组件,而始终显示的组件应使用属性动画。

  2. TransitionEffect对象是实现转场动画的核心,提供了多种转场效果的创建方法,如move、opacity、rotate等,可以通过combine方法组合多种效果,通过asymmetric方法实现非对称转场。

  3. 转场动画参数的选择是关键,需结合场景设置合适的时长、曲线和延迟,让动画更自然、流畅。

  4. 实战开发中,需兼顾动画效果与性能,通过合理设置动画参数、避免过度动画、控制转场触发条件等策略,保证转场动画的流畅稳定。

转场动画是鸿蒙应用开发中提升用户体验的重要手段,通过合理使用转场动画,可以让应用界面更加生动、流畅,为用户提供更好的交互体验。希望通过本文的讲解,开发者能够全面掌握鸿蒙转场动画的开发技巧,将其灵活运用到自身项目中,打造出既美观又实用、既流畅又高效的鸿蒙应用。

动画效果欢迎下载应用体验: 喵屿下载链接

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐