一、前言
在鸿蒙 ArkUI 项目开发里,很多页面视觉效果,开发者第一反应都是靠多层组件嵌套叠加实现。想要渐变背景就外层套容器 + 内层色块;卡片阴影单独写一层透明占位组件;图片柔光、暗角效果,直接用多张图片叠加或者引入第三方处理库。
这种写法短期能快速做出视觉效果,但项目迭代久了问题会集中暴露:页面 DOM 层级堆叠严重,引发 GPU 过度绘制,列表滑动时频繁掉帧;各处样式写死在页面内,色值、模糊参数分散,UI 改版需要逐个页面修改,很难维持全项目视觉统一。
ArkUI 内置的渐变、阴影、滤镜能力,本身就可以在单个组件上完成复杂视觉渲染,减少多余嵌套。本文基于最新 API,讲解这三类属性的高阶写法,用更少组件实现统一 UI 规范,附带可直接运行的代码示例。
二、渐变:不止纯色过渡,多色分段 + 角度定位
linearGradient 线性渐变、radialGradient 径向渐变是开发最常用的两种渐变。很多人只写两色渐变,实际上多色节点、偏移位置、角度控制,可以直接实现分割底色、渐变蒙版,省去额外叠加容器。
@Entry @Component struct GradientDemo { build() { Column() { // 线性渐变,多色分段,卡片标题背景 Text("线性渐变卡片") .width("90%") .height(80) .fontSize(18) .fontColor("#fff") .padding(16) .linearGradient({ direction: GradientDirection.EndToStart, colors: [ [0x0066ff, 0.0], [0x3399ff, 0.6], [0x66bbff, 1.0] ] }) .borderRadius(12) .margin({bottom:20}) // 径向渐变,圆形渐变蒙版 Text("径向渐变效果") .width("90%") .height(160) .fontSize(18) .fontColor("#fff") .padding(16) .radialGradient({ centerX: "50%", centerY: "50%", radius: "80%", colors: [ [0xff7722, 0.0], [0xffbb66, 1.0] ] }) .borderRadius(12) } .padding(20) .width("100%") } }colors 数组第二个参数是位置占比,取值 0~1。利用这个特性,还能实现硬分割的色块效果,不再需要两个 Row 并排叠加。
三、阴影高阶:内外阴影、多层阴影,替代悬浮遮罩组件
shadow 属性日常大多用来做卡片底部投影。很多人不知道,支持多组阴影同时声明,也可以配合 offset 调整方向,做出内阴影凹陷效果,不用额外增加一层 View 模拟凹陷。
@Entry @Component struct ShadowDemo { build() { Column() { // 多层外阴影,模拟悬浮层次感 Text("多层悬浮卡片") .width("90%") .height(100) .fontSize(18) .padding(16) .backgroundColor("#ffffff") .borderRadius(16) .shadow([ { radius: 12, color: "#10000000", offsetX: 0, offsetY: 4 }, { radius: 24, color: "#08000000", offsetX: 0, offsetY: 8 } ]) .margin({bottom:20}) // 内阴影,凹陷面板效果 Text("内阴影凹陷面板") .width("90%") .height(100) .fontSize(18) .padding(16) .backgroundColor("#f5f7fa") .borderRadius(16) .shadow({ radius: 6, color: "#20000000", offsetX: 0, offsetY: 2, isInner: true }) } .padding(20) .width("100%") } }isInner 开启后阴影向内绘制。多层阴影叠加可以营造远近层次感,原本需要嵌套两层容器才能实现的悬浮效果,现在单组件完成。
四、滤镜 filter:模糊、色相、亮度调整,图片美化免叠加
filter 滤镜可以作用在图片、容器上,支持高斯模糊、亮度、对比度、饱和度等组合调整。做图片暗角、图片变暗蒙版、背景毛玻璃,不需要叠加半透明组件,直接给组件设置 filter。
@Entry @Component struct FilterDemo { build() { Column() { Image($r("sys.media.ohos_ic_public_cover")) .width("90%") .height(180) .objectFit(ImageFit.Cover) .borderRadius(12) .filter( filterBrightness(0.8) .combine(filterSaturate(1.2)) .combine(filterBlur(2)) ) .margin({bottom:20}) Text("毛玻璃文字面板") .width("90%") .height(80) .fontSize(18) .fontColor("#fff") .textAlign(TextAlign.Center) .borderRadius(12) .backdropBlur(8) .backgroundColor("#20ffffff") } .padding(20) .width("100%") } }filter 支持链式 combine 组合多种滤镜参数。backdropBlur 是背景模糊,区别于 filterBlur,前者模糊组件后方画面,适合弹窗、卡片毛玻璃场景;后者模糊组件自身内容。
五、统一 UI:封装全局样式,消除冗余代码
项目中,卡片、渐变标题、悬浮面板样式往往多处复用。我们可以抽离 @Builder,统一管理渐变、阴影、滤镜参数,全项目复用一套视觉标准。
@Builder function CardNormal() { Column() .width("100%") .backgroundColor("#fff") .borderRadius(16) .shadow([ { radius: 12, color: "#10000000", offsetX: 0, offsetY: 4 }, { radius: 24, color: "#08000000", offsetX: 0, offsetY: 8 } ]) } @Builder function GradientTitle() { Text() .width("100%") .height(72) .linearGradient({ direction: GradientDirection.EndToStart, colors: [ [0x0066ff, 0.0], [0x3399ff, 1.0] ] }) .borderRadius({topLeft:12, topRight:12}) } @Entry @Component struct UiBuildDemo { build() { Column() { GradientTitle() CardNormal() { Text("业务卡片内容").fontSize(16).padding(16) } } .width("90%") .padding(20) } }所有视觉参数集中维护,后续 UI 改版,只修改这一处 Builder,页面全部同步更新,不用逐个页面查找修改。
六、小结
渐变、阴影、滤镜这几个属性不只是锦上添花的美化能力,更是精简组件结构、统一项目 UI 规范的工具。很多多层嵌套实现的视觉效果,都可以合并到单个组件上完成,降低页面层级,减少过度绘制。
在实际开发中,把通用视觉样式抽离为 Builder,统一管理色值、模糊半径、阴影参数。后续新增页面直接复用,既能保持视觉风格统一,也减少大量重复冗余布局代码。