鸿蒙原生 ArkTS 布局方式之 animation 隐式动画布局(API 24)
项目演示


一、什么是「隐式动画」
在 ArkUI 声明式开发范式下,UI 是数据驱动的:当被 @State、@Prop、@Link、@Provide 等装饰的状态变量发生变化时,build() 会被重新执行,组件树上对应的属性(宽高、颜色、位置、透明度等)也会随之更新。
显式动画(如 animateTo)需要开发者显式调用,并在闭包内主动修改属性;而隐式动画(animation 属性方法)则把动画能力直接「贴」在组件的属性链上——只要位于 animation() 之前的可动画属性发生变化,系统就会自动按设定的时长和曲线进行补间过渡。
一句话总结:
隐式动画 = 「属性变化」+「
animation声明」→ 系统自动补间。
这种写法更贴近声明式 UI 的心智模型,开发者只需关心「终态值」,过渡过程由系统完成,代码更简洁、可读性更高。
二、API 24 中的 animation 接口签名
在 API 24 中,animation 是 CommonAttribute 上的通用属性方法,几乎所有组件都可调用。其签名为:
animation(value: AnimateParam): T
AnimateParam 是动画参数结构体,在 API 24 中定义如下:
interface AnimateParam {
duration: number; // 动画时长,单位 ms,默认 1000,建议范围 0~30000
tempo?: number; // 播放速率,默认 1.0,>1 加速,<1 减速
curve?: Curve | string | ICurve; // 动画曲线,默认 Curve.Linear
delay?: number; // 延迟播放时间,单位 ms,默认 0
iterations?: number; // 播放次数,默认 1;-1 表示无限循环
playMode?: PlayMode; // 播放模式,默认 PlayMode.Normal
onFinish?: () => void; // 动画结束回调
onFinishFrame?: (frame: number) => void; // API 24 新增:每帧结束回调(frame 为帧索引)
expect?: () => void; // API 24 新增:期望态回调,用于自适应动画
}
参数详解
2.1 duration(时长)
- 单位毫秒(ms),默认 1000。
- 取值范围建议 0~30000;过大可能导致补间不流畅,过小则看不出过渡。
- 当
duration = 0时,等同于「立即跳变」,不会产生动画效果。
2.2 curve(动画曲线)
curve 决定属性值随时间变化的「节奏」,是动画表现力的核心。API 24 支持三种写法:
① 内置 Curve 枚举(最常用,零依赖)
enum Curve {
Linear, // 匀速
Ease, // 起止平滑
EaseIn, // 先慢后快
EaseOut, // 先快后慢
EaseInOut, // 两端平滑
FastOutSlowIn, // 快出慢入(推荐默认值,Material 风格)
LinearOutSlowIn, // 慢入匀速出
FastOutLinearIn, // 匀速入快出
ExtremeDeceleration, // 极端减速
Sharp, // 锐利
Rhythm, // 节奏
Smooth, // 平滑
Bouncing // 弹跳
}
② 字符串形式
curve: 'ease-in-out'
③ ICurve 对象(来自 @kit.ArkUI 的 curves 模块)
适合需要自定义贝塞尔、弹簧、共振曲线的高级场景:
import { curves } from '@kit.ArkUI';
curve: curves.cubicBezierCurve(0.42, 0, 0.58, 1) // 三次贝塞尔
curve: curves.springCurve({ mass: 1, stiffness: 200, damping: 15 }) // 弹簧
curve: curves.responsiveSpringMotion() // 响应式弹簧
⚠️ 注意:API 24 中
curves模块的方法名以...Curve结尾(如cubicBezierCurve、springCurve),旧版本中的cubicBezier、spring、fastOutSlowIn等不带Curve后缀的写法已废弃或不存在,编译会报Property 'xxx' does not exist on type 'typeof curves'错误。这也是初学者最常踩的坑。
2.3 tempo(播放速率)
- 默认 1.0。
tempo = 2表示 2 倍速播放(实际时长 = duration / tempo)。- 取值需 > 0,为 0 或负数会导致行为未定义。
2.4 delay(延迟)
- 延迟多少毫秒后开始播放,默认 0。
- 适合做「错峰动画」,例如列表项依次入场。
2.5 iterations(迭代次数)
- 默认 1。
- 设为
-1表示无限循环,常用于 loading 呼吸、脉冲效果。 - 设为
3表示播放 3 次后停止。
2.6 playMode(播放模式)
enum PlayMode {
Normal, // 正向播放
Reverse, // 反向播放
Alternate, // 正反交替(第 1 次正向,第 2 次反向…)
AlternateReverse // 反正交替
}
当 iterations > 1 时,Alternate 可实现「来回」效果。
2.7 onFinish / onFinishFrame(回调)
onFinish:整个动画结束时触发一次。onFinishFrame:API 24 新增,每一帧补间完成都会触发,参数frame为帧序号。可用于做与动画同步的副作用(如音效、粒子)。
三、animation 的核心规则:调用顺序
这是隐式动画最关键、也最容易踩坑的点,必须牢记:
规则 1:animation() 只对它之前声明的可动画属性生效
// ✅ 正确:可动画属性在前,animation 紧随其后
Column()
.width(this.boxWidth) // 可动画
.height(this.boxHeight) // 可动画
.backgroundColor(this.bg) // 可动画
.opacity(this.op) // 可动画
.animation({ // ← 监听以上 4 个属性
duration: 800,
curve: Curve.FastOutSlowIn
})
.justifyContent(FlexAlign.Center) // 非动画属性,写在 animation 之后
// ❌ 错误:animation 写在属性之前,动画不会生效
Column()
.animation({ duration: 800, curve: Curve.Linear })
.width(this.boxWidth) // animation 之后,不会被监听
规则 2:非可动画属性即使写在 animation 之前也不会产生动画
justifyContent、alignItems、margin 等布局属性本身不支持补间,即使写在 animation 前面也不会触发动画,但也不会报错——它们会瞬时变化。
规则 3:animation 可叠加多个
可以为一个组件声明多个 animation,每个 animation 监听其前方、且未被前一个 animation 监听的属性,从而实现「不同属性用不同曲线」:
Column()
.width(this.w)
.animation({ duration: 300, curve: Curve.Linear }) // 监听 width,用 Linear
.backgroundColor(this.bg)
.animation({ duration: 800, curve: Curve.EaseInOut }) // 监听 bgColor,用 EaseInOut
四、可动画属性清单(API 24)
并非所有属性都支持隐式动画。下面是 API 24 中常用可动画属性分类:
| 类别 | 属性 | 说明 |
|---|---|---|
| 几何 | width、height、size | 尺寸过渡 |
| 位置 | position、markAnchor、offset | 位移(不影响布局) |
| 变换 | scale、rotate、translate、transform | 仿射变换 |
| 外观 | opacity | 透明度 |
| 背景 | backgroundColor、backgroundImagePosition、backgroundImageSize | 背景相关 |
| 边框 | borderColor、borderRadius、borderWidth | 边框 |
| 阴影 | shadow | 阴影颜色/偏移/半径 |
| 文本 | fontSize、fontColor、fontWeight、letterSpacing | 文本属性 |
| 渐变 | linearGradient 内的 angle、colors 偏移 | 渐变动画 |
| 其他 | color、visibility(部分场景) | 通用属性 |
提示:
visibility在Hidden↔Visible之间是「显隐切换」而非补间;如需淡入淡出,请用opacity实现。
五、最小可运行示例
下面是一个 80 行的最小示例,演示「点击 → 属性变化 → 自动触发动画」。
// MinimalAnimationDemo.ets
@Entry
@Component
struct MinimalAnimationDemo {
@State scaleValue: number = 1;
@State bgColor: ResourceColor = '#4CAF50';
build() {
Column({ space: 30 }) {
// 可动画方块
Column() {
Text('点我')
.fontSize(24)
.fontColor(Color.White)
}
.width(160)
.height(160)
.backgroundColor(this.bgColor)
.borderRadius(20)
.scale({ x: this.scaleValue, y: this.scaleValue })
.animation({
duration: 600,
curve: Curve.FastOutSlowIn
})
.justifyContent(FlexAlign.Center)
.onClick(() => {
// 点击同时改变 scale 和颜色,animation 自动补间
this.scaleValue = this.scaleValue === 1 ? 1.4 : 1;
this.bgColor = this.bgColor === '#4CAF50' ? '#E91E63' : '#4CAF50';
})
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
}
运行效果:点击方块时,缩放与颜色变化会以 600ms 的快出慢入曲线平滑过渡,而非瞬间跳变。
六、进阶示例:多属性综合演示
下面给出一个相对完整的示例,覆盖 6 类可动画属性,并配有控制按钮。这也是本文配套的 AnimationImplicitDemo.ets 文件核心逻辑(API 24 校正版)。
// AnimationImplicitDemo.ets
@Entry
@Component
struct AnimationImplicitDemo {
@State scaleValue: number = 1;
@State rotateAngle: number = 0;
@State translateX: number = 0;
@State opacityValue: number = 1;
@State boxWidth: number = 200;
@State boxHeight: number = 200;
@State bgColor: ResourceColor = '#4CAF50';
@State radiusValue: number = 16;
build() {
Column() {
Text('animation 隐式动画布局')
.fontSize(22).fontWeight(FontWeight.Bold)
.margin({ top: 24, bottom: 16 })
// 动画展示区:所有可动画属性写在 animation 之前
Column() {
Text('ArkTS').fontSize(28).fontColor(Color.White)
}
.width(this.boxWidth)
.height(this.boxHeight)
.backgroundColor(this.bgColor)
.borderRadius(this.radiusValue)
.opacity(this.opacityValue)
.scale({ x: this.scaleValue, y: this.scaleValue })
.rotate({ angle: this.rotateAngle })
.translate({ x: this.translateX })
.animation({
duration: 800,
curve: Curve.FastOutSlowIn,
iterations: 1,
playMode: PlayMode.Normal
})
.justifyContent(FlexAlign.Center)
.margin({ top: 20, bottom: 30 })
// 缩放按钮
Button('缩放 +0.5').type(ButtonType.Capsule).backgroundColor('#2196F3')
.onClick(() => {
this.scaleValue = this.scaleValue >= 2 ? 1 : this.scaleValue + 0.5;
})
// 旋转按钮
Button('旋转 +90°').type(ButtonType.Capsule).backgroundColor('#FF9800')
.onClick(() => { this.rotateAngle += 90; })
// 平移按钮
Button('左右平移').type(ButtonType.Capsule).backgroundColor('#9C27B0')
.onClick(() => {
this.translateX = this.translateX === 0 ? 80 : 0;
})
// 透明度按钮
Button('透明度切换').type(ButtonType.Capsule).backgroundColor('#F44336')
.onClick(() => {
this.opacityValue = this.opacityValue === 1 ? 0.3 : 1;
})
// 尺寸按钮
Button('尺寸切换').type(ButtonType.Capsule).backgroundColor('#009688')
.onClick(() => {
if (this.boxWidth === 200) {
this.boxWidth = 280; this.boxHeight = 140;
} else {
this.boxWidth = 200; this.boxHeight = 200;
}
})
// 颜色 + 圆角按钮
Button('变色 + 圆角').type(ButtonType.Capsule).backgroundColor('#795548')
.onClick(() => {
if (this.bgColor === '#4CAF50') {
this.bgColor = '#E91E63'; this.radiusValue = 80;
} else {
this.bgColor = '#4CAF50'; this.radiusValue = 16;
}
})
// 一键重置
Button('重置全部').type(ButtonType.Capsule).backgroundColor('#607D8B')
.margin({ top: 16 })
.onClick(() => {
this.scaleValue = 1; this.rotateAngle = 0; this.translateX = 0;
this.opacityValue = 1; this.boxWidth = 200; this.boxHeight = 200;
this.bgColor = '#4CAF50'; this.radiusValue = 16;
})
}
.width('100%').height('100%')
.backgroundColor('#F5F5F5')
.alignItems(HorizontalAlign.Center)
}
}
代码要点解读
- 8 个
@State变量分别驱动 8 个可动画属性,互不干扰。 animation只声明一次,它统一监听其上方的 8 个属性;任一属性变化都按 800ms /FastOutSlowIn补间。- **「重置全部」**一次性改 8 个变量,系统会同时对所有变化的属性进行补间,形成「复位动画」。
- 按钮的
backgroundColor写在animation之前,但按钮没有声明animation,因此按钮颜色是瞬时切换——这正是「是否补间取决于组件自身是否声明 animation」的体现。
七、curve 曲线选型指南
不同曲线带来的观感差异巨大,选型建议如下:
| 场景 | 推荐曲线 | 理由 |
|---|---|---|
| 入场动画(淡入、放大) | Curve.EaseOut 或 FastOutSlowIn |
先快后慢,自然落位 |
| 退场动画(淡出、缩小) | Curve.EaseIn |
先慢后快,有「离开」倾向 |
| 加载呼吸、脉冲 | Curve.Smooth + iterations: -1 |
平滑循环,无突兀感 |
| 弹性反馈(点赞、点赞取消) | curves.springCurve(...) |
物理弹簧,更有生命力 |
| 列表项错峰入场 | Curve.FastOutLinearIn + 递增 delay |
节奏明快 |
| 拖拽跟随 | curves.responsiveSpringMotion() |
响应式弹簧,跟随手感 |
弹簧曲线示例(API 24 写法)
import { curves } from '@kit.ArkUI';
// 在组件属性链中
.scale({ x: this.s, y: this.s })
.animation({
duration: 1000,
curve: curves.springCurve({ mass: 1, stiffness: 200, damping: 15 })
})
弹簧曲线下,duration 仅作为上限参考,实际时长由物理参数决定。
八、隐式动画 vs 显式动画(animateTo)
两者各有适用场景,理解差异才能选对工具。
| 维度 | 隐式动画 animation |
显式动画 animateTo |
|---|---|---|
| 触发方式 | 属性值变化自动触发 | 显式调用 animateTo 闭包 |
| 写法位置 | 组件属性链中 | 业务逻辑中 |
| 终态来源 | 来自状态变量绑定 | 在闭包内修改状态 |
| 多组件联动 | 需各自声明 animation | 一个闭包可驱动多处 |
| 关键帧 | 不支持 | 配合 keyframeAnimateTo 支持 |
| 适合场景 | 简单属性过渡、交互反馈 | 复杂时序、组合动画 |
经验法则:能用隐式动画解决的,优先用隐式动画;需要精确时序控制或多组件协同的,再上 animateTo。
显式动画对照示例
// 显式动画写法(对照用)
Button('放大')
.onClick(() => {
animateTo({ duration: 600, curve: Curve.FastOutSlowIn }, () => {
this.scaleValue = 1.4; // 在闭包内修改终态
});
})
对比可见,隐式动画把「终态」直接写在属性绑定里,业务代码只需改 this.scaleValue,无需包裹闭包,更符合数据驱动的范式。
九、常见踩坑与解决方案
坑 1:animation 写在属性之后没生效
现象:点击按钮属性变了,但是「跳变」没有过渡。
原因:animation 写在了被监听属性之前。
解决:把 animation 移到所有可动画属性之后、非动画属性之前。
坑 2:curves.fastOutSlowIn 编译报错
现象:Property 'fastOutSlowIn' does not exist on type 'typeof curves'。
原因:API 24 中 curves 模块方法名以 Curve 结尾,旧写法已废弃。
解决:
- 简单场景直接用
Curve.FastOutSlowIn枚举; - 自定义曲线用
curves.cubicBezierCurve(...)、curves.springCurve(...)等带Curve后缀的方法。
坑 3:列表项动画「同时」播放
现象:列表 10 项一起入场,没有错峰感。
解决:用 delay 配合索引递增:
ForEach(this.items, (item, idx) => {
ItemView({ item })
.animation({ duration: 400, delay: idx * 60, curve: Curve.EaseOut })
})
坑 4:循环动画卡顿
现象:iterations: -1 时首尾衔接不平滑。
原因:起止值不对称,导致每次循环有「跳变」。
解决:使用 playMode: PlayMode.Alternate,让动画正反交替,自然衔接;或确保起止值相同。
坑 5:visibility 无法淡入淡出
现象:期望元素淡出消失,结果直接「闪没」。
原因:visibility 不支持补间。
解决:用 opacity 配合动画完成淡出,在 onFinish 回调里再把 visibility 设为 Hidden。
.opacity(this.visible ? 1 : 0)
.animation({
duration: 300,
curve: Curve.EaseOut,
onFinish: () => {
if (!this.visible) this.realHidden = true;
}
})
.visibility(this.realHidden ? Visibility.Hidden : Visibility.Visible)
坑 6:animation 影响首次布局
现象:页面首次加载时组件也跑了一次动画。
原因:@State 初值 → 首帧渲染,部分情况下会触发补间。
解决:用 if 条件渲染控制首帧,或在 aboutToAppear 中先设置终态、再切到初值;也可用 animateTo 显式控制首次出现。
十、性能优化建议
- 优先用变换属性:
scale、rotate、translate不触发重排,性能远高于width/height/margin。能用变换实现的,不要改尺寸。 - 避免同时对 8+ 属性做动画:单组件动画属性越多,每帧计算成本越高。核心视觉属性 ≤ 4 个为宜。
duration不宜过长:超过 1000ms 的动画容易让用户感到「迟钝」,交互反馈类建议 200~400ms。- 合理使用
iterations:无限循环动画会持续占 GPU,组件不可见时记得置为1或卸载。 onFinishFrame谨慎使用:API 24 的逐帧回调若内部逻辑过重,会拖垮动画帧率。- 列表中慎用复杂动画:长列表每项都声明 animation 会显著增加开销,建议只对「可视区+前后缓冲区」做动画。
十一、实战场景:点赞弹性反馈
下面用隐式动画实现一个类似「点赞」的弹性反馈,体现 scale + 颜色 + 弹簧曲线的组合。
// LikeButtonDemo.ets
import { curves } from '@kit.ArkUI';
@Entry
@Component
struct LikeButtonDemo {
@State liked: boolean = false;
@State scaleValue: number = 1;
@State iconColor: ResourceColor = '#999999';
build() {
Column({ space: 40 }) {
Text(liked ? '❤ 已点赞' : '♡ 点个赞吧')
.fontSize(20)
.fontColor(liked ? '#E91E63' : '#666666')
// 点赞图标
Text(liked ? '❤' : '♡')
.fontSize(80)
.fontColor(this.iconColor)
.scale({ x: this.scaleValue, y: this.scaleValue })
.animation({
duration: 800,
curve: curves.springCurve({ mass: 1, stiffness: 400, damping: 12 })
})
.onClick(() => {
this.liked = !this.liked;
// 通过先放大再回弹的「两段式终态」实现弹跳感
this.scaleValue = this.liked ? 1.6 : 0.8;
this.iconColor = this.liked ? '#E91E63' : '#999999';
// 短延迟后回弹到 1.0,触发第二次补间
setTimeout(() => { this.scaleValue = 1; }, 120);
})
}
.width('100%').height('100%')
.justifyContent(FlexAlign.Center)
}
}
要点:
- 用
springCurve物理曲线代替线性,自带「过冲」弹性。 - 通过
setTimeout制造「放大 → 回弹」两段终态,每次赋值都会触发一次补间,形成连续弹跳。 fontColor与iconColor同步过渡,颜色与缩放共享同一段 animation。
十二、实战场景:卡片翻转
利用 rotate 的 Y 轴旋转 + 透明度切换,模拟卡片翻转:
// CardFlipDemo.ets
@Entry
@Component
struct CardFlipDemo {
@State flipped: boolean = false;
@State rotateY: number = 0;
@State opacityVal: number = 1;
@State cardText: string = '正面';
build() {
Column({ space: 30 }) {
Column() {
Text(this.cardText).fontSize(28).fontColor(Color.White)
}
.width(220).height(300)
.backgroundColor(this.flipped ? '#3F51B5' : '#FF7043')
.borderRadius(16)
.rotate({ y: 1, angle: this.rotateY }) // 绕 Y 轴旋转
.opacity(this.opacityVal)
.animation({ duration: 600, curve: Curve.FastOutSlowIn })
.justifyContent(FlexAlign.Center)
Button('翻转卡片')
.onClick(() => {
// 旋转到 90° 时切换内容(视觉上「侧立」的瞬间)
this.rotateY += 90;
setTimeout(() => {
this.flipped = !this.flipped;
this.cardText = this.flipped ? '背面' : '正面';
}, 300);
})
}
.width('100%').height('100%')
.justifyContent(FlexAlign.Center)
}
}
提示:ArkUI 的
rotate默认绕中心轴旋转,绕 Y 轴 90° 时组件「侧立」几乎不可见,此时切换内容即可实现翻转错觉。若需真正的 3D 翻转,可结合transform矩阵或两块叠加卡片分别绕 Y 轴 ±90° 旋转。
十三、与 API 24 其他动画能力联动
API 24 的动画体系是一个完整的「矩阵」,animation 是其中最轻量的一环。理解它在体系中的定位,才能组合出更丰富的效果:
| 能力 | 接口 | 定位 |
|---|---|---|
| 隐式属性动画 | animation |
本文主角,轻量声明式 |
| 显式属性动画 | animateTo |
闭包驱动,可包含多条状态修改 |
| 关键帧动画 | keyframeAnimateTo |
多关键帧、不同曲线 |
| 组件转场 | transition |
插入/移除时的入场出场 |
| 共享元素转场 | sharedTransition |
页面间共享元素飞越 |
| 粒子 / 物理动画 | particle、springMotion |
高级特效 |
| 绑定手势动画 | panGesture + responsiveSpringMotion |
拖拽跟随 |
典型组合:隐式动画负责属性过渡,transition 负责组件插入/移除,二者互补。例如:
if (this.showBadge) {
Text('NEW')
.transition({ type: TransitionType.All, opacity: 0, translate: { y: -20 } })
.opacity(this.badgeOpacity)
.animation({ duration: 300, curve: Curve.EaseOut })
}
十四、小结
animation 隐式动画布局是 ArkUI 声明式范式中「最贴近数据驱动心智」的动画方式。掌握它的关键在于三件事:
- 顺序:可动画属性在前,
animation紧随其后,非动画属性再写后面。 - 曲线:用
Curve枚举应对 90% 场景,用curves.xxxCurve处理物理曲线,注意 API 24 方法名带Curve后缀。 - 属性选型:优先用
scale/rotate/translate/opacity等变换类属性,性能最佳;width/height/margin等布局属性次之;visibility等不支持补间的属性要用opacity间接实现。
把这三点内化后,绝大多数交互反馈、状态过渡都能用 3~5 行 animation 优雅解决,无需复杂的显式动画代码。
附录 A:完整可运行工程结构
entry/src/main/ets/pages/
├── Index.ets # 入口页,提供跳转按钮
├── AnimationImplicitDemo.ets # 多属性综合演示(第六章)
├── MinimalAnimationDemo.ets # 最小示例(第五章)
├── LikeButtonDemo.ets # 点赞弹性反馈(第十一章)
└── CardFlipDemo.ets # 卡片翻转(第十二章)
entry/src/main/resources/base/profile/main_pages.json
{
"src": [
"pages/Index",
"pages/AnimationImplicitDemo",
"pages/MinimalAnimationDemo",
"pages/LikeButtonDemo",
"pages/CardFlipDemo"
]
}
附录 B:API 24 curves 模块常用方法速查
| 方法 | 用途 |
|---|---|
curves.cubicBezierCurve(x1, y1, x2, y2) |
三次贝塞尔曲线 |
curves.springCurve({ mass, stiffness, damping, velocity }) |
物理弹簧 |
curves.springMotion(response, dampingFraction, overlapDuration) |
弹簧运动(适合手势) |
curves.responsiveSpringMotion(response, dampingFraction, overlapDuration) |
响应式弹簧运动 |
curves.customCurve(...) |
自定义插值函数 |
旧写法
curves.cubicBezier、curves.spring、curves.fastOutSlowIn、curves.easeIn等在 API 24 中已废弃或不存在,请统一改用带Curve后缀的新方法,或直接使用Curve枚举。
附录 C:Curve 枚举速查表
| 枚举值 | 别名 | 表现 |
|---|---|---|
Curve.Linear |
linear | 匀速 |
Curve.Ease |
ease | 起止平滑 |
Curve.EaseIn |
ease-in | 先慢后快 |
Curve.EaseOut |
ease-out | 先快后慢 |
Curve.EaseInOut |
ease-in-out | 两端平滑 |
Curve.FastOutSlowIn |
— | 快出慢入(推荐默认) |
Curve.LinearOutSlowIn |
— | 匀速入慢出 |
Curve.FastOutLinearIn |
— | 快入匀速出 |
Curve.ExtremeDeceleration |
— | 极端减速 |
Curve.Sharp |
— | 锐利 |
Curve.Rhythm |
— | 节奏 |
Curve.Smooth |
— | 平滑 |
Curve.Bouncing |
— | 弹跳 |
版本声明:本文所有 API、参数、方法名均以 HarmonyOS NEXT API 24 为准。后续版本如有变更,请以官方文档为准。
更多推荐




所有评论(0)