鸿蒙新特性实战:视觉特效 — shadow/blur/backdropBlur/grayscale 十种组件滤镜
引言
在现代移动应用设计中,视觉特效是塑造品牌调性和提升用户体验的关键因素。阴影营造层次感、模糊制造焦点、灰度传达禁用状态、色相旋转让色彩随主题流动——这些效果在过去往往依赖设计师切图或自定义绘制实现,但现在,它们可以直接在 ArkUI 组件上通过声明式属性的方式完成。
HarmonyOS NEXT 为所有 ArkUI 组件内置了一套完整的视觉特效属性系统,包含十种滤镜效果:
- shadow — 阴影投影,控制半径/偏移/颜色
- blur — 高斯模糊,让组件产生失焦效果
- backdropBlur — 背景模糊,模糊组件后方的下层内容(毛玻璃/磨砂效果)
- grayscale — 灰度滤镜,彩色变黑白
- brightness — 亮度调节,0 = 全黑,1 = 原始,>1 = 更亮
- contrast — 对比度调节,控制明暗差异
- saturate — 饱和度调节,0 = 去色,>1 = 更鲜艳
- sepia — 怀旧泛黄滤镜,制造复古感
- invert — 反色滤镜,暗色模式图像适配
- hueRotate — 色相旋转,沿 360 度色相环变换
- colorBlend — 颜色混合叠加,为组件覆盖一层色调
这些属性的威力在于可组合性——同一组件可以同时应用多种滤镜,通过 @State 驱动的参数实时调节,天然支持所有属性动画。
本文构建一个视觉特效实验室 Demo,通过 10 个特效选项卡切换、滑块实时调节参数、实时预览区展示效果、毛玻璃卡片演示 backdropBlur、滤镜链叠加演示等功能,全面探索这套视觉特效系统的能力和应用场景。
读完本文,你将掌握:
- shadow:radius/color/offsetX/offsetY 四参数控制阴影形态
- blur vs backdropBlur:前向模糊与后向模糊的本质差异
- 五种色彩滤镜:grayscale/brightness/contrast/saturate/hueRotate 的使用方式与取值含义
- sepia + invert + colorBlend:特殊视觉效果与暗色模式适配
- 滤镜链叠加:多滤镜同时应用的执行顺序与视觉效果
- 与 CSS filter 的对比:让 Web 开发者快速理解 ArkUI 滤镜属性
一、视觉特效体系总览
1.1 十一种特效属性一览
| 属性 | 类型 | 取值说明 | 默认值 | 动画 |
|---|---|---|---|---|
.shadow({ radius, color, offsetX, offsetY }) |
ShadowOptions |
阴影配置对象 | 无阴影 | 支持 |
.blur(value) |
number |
高斯模糊半径 (vp),0 = 无模糊 | 0 |
支持 |
.backdropBlur(value) |
number |
背景模糊半径 (vp),0 = 无模糊 | 0 |
支持 |
.grayscale(value) |
number |
灰度值,0.0(彩色) ~ 1.0(完全黑白) | 0.0 |
支持 |
.brightness(value) |
number |
亮度,0.0(全黑) ~ 1.0(原始) ~ ∞(过曝) | 1.0 |
支持 |
.contrast(value) |
number |
对比度,0.0(灰) ~ 1.0(原始) ~ ∞(强对比) | 1.0 |
支持 |
.saturate(value) |
number |
饱和度,0.0(去色) ~ 1.0(原始) ~ ∞(过饱和) | 1.0 |
支持 |
.sepia(value) |
number |
怀旧褐变,0.0(正常) ~ 1.0(完全泛黄) | 0.0 |
支持 |
.invert(value) |
number |
反色程度,0.0(正常) ~ 1.0(完全反色) | 0.0 |
支持 |
.hueRotate(value) |
number |
色相旋转角度 (度),0° ~ 360° | 0 |
支持 |
.colorBlend(color) |
ResourceColor |
叠加混合的颜色(配合透明度控制强度) | Color.Transparent |
支持 |
重要特性:
- 所有滤镜属性都可以同时叠加使用——顺序不影响最终效果(每个滤镜独立计算后叠加)
- 所有属性都支持
animateTo动画,可以实现从模糊到清晰、从灰度到彩色等平滑过渡 - 滤镜应用范围:适用于所有 ArkUI 组件,包括 Text、Image、Column、Row 以及自定义组件
1.2 与 CSS filter 的对比
对于有 Web 前端开发经验的开发者,ArkUI 的视觉特效属性与 CSS 的 filter 和 box-shadow 高度对应:
| ArkUI 属性 | CSS 对应 | 差异 |
|---|---|---|
.shadow({...}) |
box-shadow: ... |
ArkUI 使用对象配置,CSS 使用空格分隔值 |
.blur(N) |
filter: blur(Npx) |
ArkUI 没有单位后缀,直接传数字 |
.backdropBlur(N) |
backdrop-filter: blur(Npx) |
语义完全一致 |
.grayscale(V) |
filter: grayscale(V) |
取值含义相同:0 = 彩色,1 = 黑白 |
.brightness(V) |
filter: brightness(V) |
取值含义相同:1 = 原始亮度 |
.contrast(V) |
filter: contrast(V) |
取值含义相同:1 = 原始对比度 |
.saturate(V) |
filter: saturate(V) |
取值含义相同:1 = 原始饱和度 |
.sepia(V) |
filter: sepia(V) |
取值含义相同 |
.invert(V) |
filter: invert(V) |
取值含义相同 |
.hueRotate(D) |
filter: hue-rotate(D deg) |
CSS 需要带 deg 单位 |
.colorBlend(C) |
无直接对应 | 类似 mix-blend-mode 但更简单 |
CSS 开发者可以几乎零学习成本地切换到 ArkUI 的视觉特效系统。
1.3 blur 与 backdropBlur 的本质区别
这是最容易混淆的两个属性,但它们的行为完全不同:
// blur:把当前组件本身变模糊
Column() {
Text('这行文字会变模糊')
}
.blur(4) // 组件自身变模糊
// backdropBlur:模糊当前组件后面的内容(组件本身保持清晰)
Stack() {
Image($r('app.media.background')) // 底层的背景图
Column() {
Text('这行文字清晰')
}
.backdropBlur(10) // 模糊的是下方的图片,不是文字本身
.backgroundColor('#30FFFFFF') // 半透明背景,让模糊效果可见
}
核心差异表:
| 维度 | blur | backdropBlur |
|---|---|---|
| 模糊对象 | 当前组件自身 | 当前组件后方的内容 |
| 当前组件内容 | 变模糊 | 保持清晰 |
| 典型场景 | 失焦转场、加载态 | 毛玻璃导航栏、iOS 风格弹窗 |
| 需要半透明背景 | 不需要 | 通常需要 .backgroundColor('#30FFFFFF') |
| 性能开销 | 低 | 中(需要读取底层渲染结果) |
二、shadow — 阴影投影详解
shadow 是所有视觉特效中最基础也最常用的属性。它通过四个参数控制阴影的形态:
.shadow({
radius: number, // 阴影模糊半径,值越大阴影越柔和、扩散越远
color: string, // 阴影颜色,支持 #RGBA 格式
offsetX: number, // X 方向偏移量,正数向右,负数向左
offsetY: number // Y 方向偏移量,正数向下,负数向上
})
2.1 radius — 模糊半径
radius 控制阴影的模糊扩散程度。radius 为 0 时阴影边缘锐利如边框,radius 越大,阴影越柔和、扩散越远:
radius = 0: 阴影边缘清晰,类似 solid border
radius = 6: 柔和过渡,典型 Material Design "Elevation 2"
radius = 12: 明显扩散,Material Design "Elevation 4"
radius = 24: 大面积柔光,适合悬浮面板
radius = 40: 极柔效果,适合大面积品牌色辉光
2.2 offsetX / offsetY — 偏移量
偏移量控制阴影投射方向:
offsetX = 0, offsetY = 6 → 正下方投影(默认卡片阴影)
offsetX = 0, offsetY = -4 → 正上方投影(底部导航栏)
offsetX = 6, offsetY = 6 → 右下角投影(光源在左上)
offsetX = -6, offsetY = 6 → 左下角投影(光源在右上)
offsetX = 0, offsetY = 0 → 四周均匀扩散(辉光效果)
2.3 color — 阴影颜色
阴影颜色直接影响视觉效果。常见的实践:
'#20000000' — 浅黑影(Elevation 2 的经典用法)
'#40000000' — 中等黑影(Elevation 4)
'#80000000' — 深黑影(Elevation 8+)
'#203B82F6' — 蓝色辉光(品牌色发光)
'#40EF4444' — 红色辉光(错误/警告态)
'#00000000' — 透明(无阴影)


三、blur — 高斯模糊详解
blur 将组件整体应用高斯模糊效果,包括该组件内的所有子组件:
Column() {
Text('Hello HarmonyOS')
.fontSize(20)
}
.blur(4) // 整个 Column 变模糊
blur 值可以超过 10,但超过 5 后变化趋于饱和——从 0 到 3 的变化非常明显,从 5 到 8 的差异较小。
典型应用场景
- 失焦转场:页面退出或弹窗打开时,使用
animateTo将页面从blur(0)过渡到blur(4),营造景深效果 - 加载中占位:内容加载中时给区域设置
blur(2),让用户感知数据正在刷新 - 隐私保护:敏感数据(如余额、身份证号)可通过
blur(8)遮盖,点击后平滑过渡到blur(0) - 背景装饰:大面积色彩区块配合
blur(2)+brightness(0.8)营造磨砂质感背景
四、backdropBlur — 毛玻璃/磨砂背景详解
backdropBlur 是 iOS 风格毛玻璃效果的核心属性。它模糊当前组件后方的所有下层内容,而组件自身保持清晰——这正是 iOS 导航栏、控制中心、通知中心的标志性视觉效果。
4.1 实现要点
要正确实现毛玻璃效果,必须满足三个条件:
- 使用 Stack 布局:
backdropBlur模糊的是 Z 轴下层的内容,必须用Stack让内容在 Z 轴上存在"下方" - 设置半透明背景色:
.backgroundColor('#30FFFFFF')—— 如果不设背景色,模糊效果肉眼不可见 - 覆盖在下层内容上方:毛玻璃组件需要和下层内容在相同
Stack内,并且位于上方
Stack() {
// 底层:要被模糊的内容
Image($r('app.media.background'))
.width('100%')
.height(200)
// 顶层:毛玻璃卡片
Column() {
Text('超有质感的毛玻璃卡片')
.fontSize(14)
.fontColor('#FFFFFF')
}
.width(180)
.height(60)
.borderRadius(12)
.backdropBlur(10) // 模糊下方图片
.backgroundColor('#30FFFFFF') // 半透明白色让模糊可见
}
4.2 blur 值选择指南
| blur 值 | 视觉效果 | 适用场景 |
|---|---|---|
| 2-4 | 微妙雾化,下层内容仍然可辨 | 导航栏、标签栏 |
| 5-8 | 中等模糊,下层轮廓可见但不可读 | 底部弹出层、操作菜单 |
| 9-15 | 明显模糊,下层仅剩色块感 | 弹窗、提示卡片 |
| 16-20 | 强烈模糊,下层完全模糊化 | 全屏遮罩、控制中心 |
五、grayscale / brightness / contrast / saturate / sepia — 五种色彩滤镜
5.1 grayscale — 灰度
grayscale(v) 将组件色彩转换为灰度效果。v 从 0.0(彩色)到 1.0(完全黑白):
0.0 — 原始色彩
0.3 — 轻微褪色
0.5 — 明显灰调
0.7 — 接近黑白
1.0 — 完全黑白
典型应用:
- 禁用态:已失效的链接或选项用
grayscale(0.6)表示不可用 - 已读/历史:消息列表中已读消息用
grayscale(0.3)区分 - 时间印记:旧条目逐渐增加灰度,暗示时间流逝
- 暗色模式过渡:配合
invert实现平滑的明暗切换
5.2 brightness — 亮度
brightness(v) 调节组件亮度。1.0 为原始亮度:
0.0 — 完全变黑
0.3 — 深暗
0.7 — 偏暗
1.0 — 原始
1.5 — 明亮
2.0 — 强烈过曝
3.0 — 几乎全白
注意:brightness 可以大于 1.0,用于制造高亮闪烁效果。
5.3 contrast — 对比度
contrast(v) 调节亮部与暗部的差异:
0.0 — 完全灰色(无对比度)
0.5 — 低对比度,画面发灰
1.0 — 原始对比度
1.5 — 高对比度,色彩鲜明
2.0 — 极高对比度
高对比度可以增强文字可读性,低对比度可以制造 低饱和的柔和氛围。
5.4 saturate — 饱和度
saturate(v) 调节色彩饱和度:
0.0 — 完全去色(等价于 grayscale(1.0))
0.5 — 半饱和,色调偏淡
1.0 — 原始饱和度
1.5 — 鲜艳
2.0 — 高饱和,色彩夺目
3.0 — 过饱和
saturate(0) 和 grayscale(1.0) 的视觉效果相同(都是黑白),但算法不同:
saturate是移除色彩信息(通过色彩空间转换)grayscale是基于亮度权重的灰度转换(R×0.299 + G×0.587 + B×0.114)
5.5 sepia — 怀旧泛黄
sepia(v) 将组件施加褐变/泛黄效果:
0.0 — 正常
0.3 — 轻微泛黄
0.6 — 明显复古
1.0 — 完全怀旧褐变
sepia 的效果类似于老照片——暖棕色调取代原始色彩。
典型应用:复古滤镜、时间印记、历史记录时间线中更久远的数据用更高的 sepia 值。
六、invert / hueRotate / colorBlend — 特殊效果
6.1 invert — 反色
invert(v) 将色彩反转,类似于照片底片效果:
0.0 — 正常
0.5 — 中间灰(所有通道半反转)
1.0 — 完全反色
反色在暗色模式的图像适配中有实际价值:当应用切换到暗色主题时,某些浅色图标/插图可以通过 invert(0.85) 转化为暗色版本,避免重新准备资源。
6.2 hueRotate — 色相旋转
hueRotate(deg) 沿 HSL 色相环旋转色彩:
0° — 原始
60° — 红色变黄色,绿色变青色,蓝色变品红
120° — 红色变绿色
180° — 红色变青色(互补色)
240° — 红色变蓝色
300° — 红色变品红
360° — 回到原始(完整一圈)
hueRotate 是动态色彩变化/主题切换的利器。通过 animateTo 平滑旋转 hueRotate 值,可以实现令人惊叹的"彩虹循环"动画。
6.3 colorBlend — 颜色混合
colorBlend(color) 将指定颜色混合叠加到组件上:
.colorBlend('#406366F1') // 叠加 25% 透明度紫色
通过调节叠加颜色的 Alpha 值来控制混合强度:
'#FF6366F1'(完全不透明)→ 几乎覆盖原始颜色'#206366F1'(12.5% 透明)→ 微妙色调偏移Color.Transparent(全透明)→ 无效果
七、滤镜链叠加
这是这套系统最强大的特性——所有滤镜可以同时应用于同一组件:
Column() { /* 内容 */ }
.shadow({ radius: 12, color: '#20000000', offsetX: 0, offsetY: 6 })
.blur(0.5)
.grayscale(0.3)
.brightness(1.1)
.contrast(1.05)
.saturate(1.2)
.sepia(0.1)
.invert(0)
.hueRotate(15)
.colorBlend(Color.Transparent)
滤镜执行顺序与属性书写顺序无关——系统内部按固定顺序处理(先色彩滤镜、后模糊、后阴影),确保每次组合的结果可预测。
实战提示:
- 阴影 + 暗淡(saturate(0.3) + brightness(0.6))→ 制造"不可用"的禁用态卡片
- sepia(0.4) + brightness(0.8) + contrast(1.1) → 复古照片风格
- blur(0.5) + brightness(1.2) + saturate(0.8) → 柔和的磨砂质感背景
八、实战 Demo:视觉特效实验室
页面结构
视觉特效实验室
├── 标题栏 — "视觉特效实验室" + "shadow / blur / filter"
├── 特效类型选择器(水平滚动的标签栏)
│ └── 阴影 / 模糊 / 灰度 / 亮度 / 对比 / 饱和 / 怀旧 / 反色 / 色相 / 混合
├── 实时预览区
│ ├── 虚线边框演示画布(Stack 布局用于 backdropBlur 演示)
│ │ ├── 底层 Image 作为毛玻璃模糊源
│ │ └── 毛玻璃卡片(仅模糊模式下可见)
│ └── 特效演示卡片(同时应用所有 10 种滤镜)
│ └── 显示 "特效演示" + "HarmonyOS Visual FX"
├── 参数调节区(按当前选中的特效类型动态变化)
│ ├── 阴影:模糊半径滑块 + X偏移 + Y偏移 + 颜色圆点
│ ├── 模糊:模糊值滑块 + 背景模糊滑块 + 说明文字
│ ├── 灰度/亮度/对比/饱和/怀旧/反色/色相:各自专用滑块
│ └── 颜色混合:六色圆点选择器
├── 当前特效数值表(2×4 网格显示所有参数当前值)
├── 十种特效参考卡片(API 名称 + 参数 + 应用场景)
└── 核心 API 参考 — 12 个关键 API/属性
4 个交互点
- 10 种特效类型切换 — 点击顶部水平滚动的标签栏切换当前编辑的特效类型,预览区卡片实时响应
- 参数滑块调节 — 每种特效有独立的滑块控件,拖动滑块实时更新预览卡片
- 颜色圆点选择器 — 阴影和颜色混合模式提供 5-6 种预设颜色圆点,点击立即切换
- 毛玻璃效果演示 — 模糊模式下叠加的毛玻璃卡片通过 backdropBlur 实时模糊下层图片,调节滑块观察从清晰到磨砂的连续变化
核心代码实现
特效类型切换与动态控件
@State activeTab: number = 0;
tabs: string[] = ['阴影', '模糊', '灰度', '亮度', '对比', '饱和', '怀旧', '反色', '色相', '混合'];
build() {
// 特效类型选择器
Row() {
Scroll() {
Row() {
ForEach(this.tabs, (name: string, idx: number) => {
Text(name)
.fontSize(11)
.fontColor(idx === this.activeTab ? '#FFFFFF' : '#374151')
.fontWeight(idx === this.activeTab ? FontWeight.Bold : FontWeight.Normal)
.padding({ left: 12, right: 12, top: 6, bottom: 6 })
.borderRadius(6)
.backgroundColor(idx === this.activeTab ? '#6366F1' : '#F3F4F6')
.margin({ right: 6 })
.onClick(() => { this.activeTab = idx; })
})
}
}
.scrollable(ScrollDirection.Horizontal)
.scrollBar(BarState.Off)
}
}
按 activeTab 值(0 到 9)条件渲染对应的参数调节控件:滑块、颜色选择器、说明文字等。
预览卡片同时应用所有滤镜
演示卡片同时应用全部 10 种滤镜属性:
Row() {
Column() {
Text('特效演示')
.fontSize(16)
.fontColor('#FFFFFF')
.fontWeight(FontWeight.Bold)
Text('HarmonyOS Visual FX')
.fontSize(11)
.fontColor('#FFFFFF90')
}
.width(200)
.height(100)
.justifyContent(FlexAlign.Center)
.borderRadius(10)
.backgroundColor('#6366F1')
.shadow({
radius: this.shadowRadius,
color: this.shadowColor,
offsetX: this.shadowOffsetX,
offsetY: this.shadowOffsetY
})
.blur(this.blurValue)
.grayscale(this.grayscaleValue)
.brightness(this.brightnessValue)
.contrast(this.contrastValue)
.saturate(this.saturateValue)
.sepia(this.sepiaValue)
.invert(this.invertValue)
.hueRotate(this.hueRotateValue)
.colorBlend(this.blendColor !== '#00000000' ? this.blendColor : Color.Transparent)
}
所有滤镜状态通过 @State 变量驱动,滑块调节后立即自动重绘。
通用滑块构建器
@Builder
sliderRow(label: string, value: number, min: number, max: number, onChange: (v: number) => void) {
Row() {
Text(label)
.fontSize(11)
.fontColor('#6B7280')
.width(56)
Slider({ value: value, min: min, max: max, step: (max - min) / 100 })
.width('40%')
.onChange(onChange)
Text(value.toFixed(2))
.fontSize(11)
.fontColor('#6366F1')
.fontWeight(FontWeight.Medium)
.fontFamily('monospace')
.margin({ left: 8 })
.width(50)
}
.width('100%')
.margin({ bottom: 6 })
}
这个 Builder 在阴影(3 个滑块)、模糊(2 个滑块)、灰度/亮度/对比/饱和/怀旧/反色/色相(各 1 个滑块)中通用。
毛玻璃演示
Stack() {
// 底层:要被模糊的内容
Column() {
Image($r('app.media.startIcon'))
.width(120)
.height(120)
.objectFit(ImageFit.Cover)
.borderRadius(8)
}
.width('100%')
.height(180)
.justifyContent(FlexAlign.Center)
// 顶层毛玻璃卡片(仅在模糊模式下显示)
if (this.activeTab === 1 && this.backdropBlurValue > 0) {
Column() {
Text('毛玻璃效果 ' + this.backdropBlurValue.toFixed(0) + 'px')
.fontSize(14)
.fontColor('#FFFFFF')
.fontWeight(FontWeight.Bold)
}
.width(180)
.height(60)
.borderRadius(12)
.justifyContent(FlexAlign.Center)
.backdropBlur(this.backdropBlurValue)
.backgroundColor('#30FFFFFF')
}
}
预览效果预期
- 阴影模式:演示卡片有明显的投影效果,调节半径从 0 到 40,阴影从锐利变为柔和辉光;调节偏移量观察光源方向变化
- 模糊模式:两个滑块——上方控制卡片自身模糊,下方控制毛玻璃卡片的背景模糊。毛玻璃卡片下的图片逐渐从清晰变为磨砂
- 灰度模式:滑块从 0 到 1,演示卡片色彩从彩色逐渐变为黑白
- 亮度/对比/饱和:滑块从 0 到 3,下探到 0 变黑/变灰/变暗,拉伸到 3 变白/变强/变艳
- 怀旧模式:滑块从 0 到 1,卡片逐渐泛黄呈现复古相片质感
- 反色模式:滑块从 0 到 1,卡片色彩逐渐反转(靛蓝变浅橙、白色变黑色)
- 色相模式:滑块从 0° 到 360°,卡片底色在彩虹色之间平滑旋转
- 混合模式:点击不同颜色圆点,卡片叠加对应色调(靛蓝/红/绿/橙/紫色 + 透明)
九、实战技巧与常见问题
9.1 阴影性能优化
shadow 属性涉及 GPU 合成层,在大量组件上使用时注意:
- 限制列表中单屏可见项的阴影数量(配合
LazyForEach自然约束) - 对于不动的静态卡片使用
shadow完全无问题(通常 50+ 项都没压力) - 动画中的阴影可能触发每帧重合成,保持 radius 值在 20 以内以降低 GPU 开销
9.2 backdropBlur 不可见问题排查
如果设置了 backdropBlur 但看不到效果,按以下顺序检查:
- 是否使用了
Stack布局?(backdropBlur需要下层内容存在) - 是否设置了半透明背景色?(
.backgroundColor('#30FFFFFF')才能让模糊可见) - 下层是否有实际内容可以模糊?(空白或纯色区域看不出效果)
- blur 值是否太小?(< 2 时效果很弱)
9.3 滤镜组合的实际应用
禁用态卡片:
Card()
.grayscale(0.6)
.brightness(0.85)
.opacity(0.7)
暗色模式图像适配:
Image($r('app.media.light_icon'))
.invert(0.9)
.hueRotate(180)
品牌色辉光:
Card()
.shadow({ radius: 24, color: '#403B82F6', offsetX: 0, offsetY: 0 })
十、总结
ArkUI 的视觉特效属性系统为 HarmonyOS 开发者提供了一套声明式的、与 CSS filter 高度对应且功能完整的组件级滤镜工具:
- shadow 四参数控制阴影,从锐利边框到柔和辉光全覆盖
- blur / backdropBlur 分别实现前向模糊和背景模糊,后者是毛玻璃效果的基石
- 五种色彩滤镜(grayscale/brightness/contrast/saturate/sepia)提供完整的图像调色能力
- 三种特殊效果(invert/hueRotate/colorBlend)覆盖反色、色彩旋转、色调叠加等高级需求
- 滤镜链叠加让开发者可以任意组合,创造出独特的视觉效果
- 声明式 + @State 驱动让特效参数调节天然流畅,无需手动重绘
- animateTo 支持让特效之间的过渡无缝平滑
这套系统不需要任何图片资源、不需要自定义绘制、不需要第三方库——所有效果通过纯属性链式调用即可实现。对于追求精致 UI 和流畅交互的 HarmonyOS 应用来说,它是工具箱中不可或缺的一部分。
结合 animateTo 属性动画,可以实现从模糊到清晰的过渡、从黑白到彩色的复活、从阴影到辉光的转变——而这些只需要改变一个 @State 变量的值。
更多推荐




所有评论(0)