20分钟搞定 Compose 毛玻璃与玻璃拟态效果
本教程带你快速上手 Haze 2 库,20 分钟内为 Compose 页面添加毛玻璃模糊和玻璃拟态效果。涵盖模块化配置、实战代码、性能调优与多平台避坑指南。学完即可直接在项目中集成高级 UI 效果。

给你的 Compose 页面加上毛玻璃效果:Haze 2 实战教程
为什么你需要毛玻璃效果?
做 UI 开发时,产品需求里总会出现那句「加个半透明毛玻璃背景,高级感就出来了」。在 Compose 中徒手实现这个效果,过去往往需要自定义 Canvas 绘制或者寻找功能单一的第三方方案。这类方案不仅性能堪忧、边缘容易出现锯齿,而且大多只支持 Android,一旦涉及跨平台交付就非常头疼。
Haze 库由 Android 领域知名开发者 chrisbanes 维护,全面覆盖 Android、iOS、macOS、Desktop 以及 Web 平台。最新的 2.0 版本对底层架构进行了重构,采用模块化设计与全新的「源-效果」分离 API。本教程带你从零接入,用不到二十分钟为你的 Compose 界面集成专业的模糊与拟物效果。
开发环境准备
确保你的项目满足以下基础配置:
- 运行环境为 Jetpack Compose 或 Compose Multiplatform
- Kotlin 版本 2.0+(最低支持 1.9+)
- 熟悉
Modifier链式调用、Box布局容器与remember状态管理的基本用法 - 若进行多平台开发,需确认目标平台模块已正确配置
本教程以 Android 为主线演示,涉及多平台差异的地方会单独标注。
接入 Haze 2:按需引入模块
Haze 2 摒弃了传统的单体依赖,改为按需加载的模块化架构。很多新手容易在这个环节踩坑:直接引入所有模块导致包体积膨胀,或者混用不同版本造成编译冲突。
核心模块划分逻辑如下:
haze:基建核心,提供hazeSource源图层捕获能力与扩展 APIhaze-blur:毛玻璃模糊渲染引擎haze-blur-materials:强烈建议引入,内置薄、常规、厚三种预制模糊样式haze-glass:玻璃拟态渲染引擎(实验性特性)haze-glass-material3:适配 Material3 设计规范的玻璃样式
在你的 build.gradle.kts 文件中(Compose Multiplatform 项目请放在 commonMain 依赖块),添加如下配置:
kotlin
val hazeVersion = "2.0.0-beta03"
dependencies {
implementation("dev.chrisbanes.haze:haze:$hazeVersion")
implementation("dev.chrisbanes.haze:haze-blur:$hazeVersion")
implementation("dev.chrisbanes.haze:haze-blur-materials:$hazeVersion")
// 如需玻璃拟态效果,取消下面这行的注释
// implementation("dev.chrisbanes.haze:haze-glass:$hazeVersion")
}
注意保持所有 dev.chrisbanes.haze 开头的 artifact 版本号绝对一致。当前版本处于 Beta 阶段,旧版 1.x 用户迁移时需查阅官方指南,核心变更在于链式调用被替换为 hazeBlur/hazeGlass 配合 HazeInput 和 Style 的新范式。
场景一:图片上方叠加毛玻璃标题栏
这是 UI 开发中最经典的组合:背景大图,上方覆盖半透明模糊层承载文字。在深入代码之前,理解 Haze 2 的底层图形学机制能帮你避开大量布局错乱问题。Haze 不依赖传统的 View 截图,而是利用 Compose 原生的 GraphicsLayer 进行离屏渲染捕获。这意味着源图层的内容变化会实时同步到效果层,且不会触发额外的 UI Tree 遍历。
kotlin
@Composable
fun FrostedGlassImageDemo(painter: Painter) {
val hazeState = rememberHazeState()
Box {
Image(
painter = painter,
contentDescription = null,
modifier = Modifier
.fillMaxSize()
.hazeSource(hazeState),
)
Box(
modifier = Modifier
.align(Alignment.BottomCenter)
.fillMaxWidth()
.height(200.dp)
.hazeBlur(
input = HazeInput.Sources(hazeState),
style = HazeMaterials.thick(),
)
.padding(16.dp)
) {
Text(
text = "这张图的底部标题",
color = Color.White,
style = MaterialTheme.typography.headlineSmall,
)
}
}
}
rememberHazeState() 充当数据中转站,负责在源内容与效果层之间传递捕获的图形数据。配合 remember 使用,可避免重组时状态意外重置。
Modifier.hazeSource(hazeState) 标记源图层,Haze 底层会抓取该区域的所有渲染像素。
Modifier.hazeBlur(...) 负责渲染效果。传入 HazeInput.Sources(hazeState) 明确告知渲染器:模糊素材来自前面标记的源图层。
这套设计的精妙之处在于「解耦」。源图层可以是任意 Composable,效果层作为独立视图叠加,生命周期互不干扰。如果希望模糊效果层自身的子组件,只需将输入源替换为 HazeInput.Content,这在制作浮动面板时极为实用。性能调优方面,HazeInput 提供了 scaleFactor 参数,适当降低该值能在几乎不损失视觉观感的前提下,将 GPU 着色器的计算量大幅削减。
场景二:打造玻璃拟态卡片
玻璃拟态在 Blur 基础上引入了折射率、边缘高光与圆角过渡,视觉效果更具空间层次感。使用 haze-glass 模块前,请留意其标注了 @ExperimentalHazeApi。
kotlin
@OptIn(ExperimentalHazeApi::class)
@Composable
fun GlassCardDemo(painter: Painter) {
val hazeState = rememberHazeState()
Box {
Image(
painter = painter,
contentDescription = null,
modifier = Modifier
.fillMaxSize()
.hazeSource(hazeState),
)
Box(
modifier = Modifier
.align(Alignment.Center)
.size(280.dp, 160.dp)
.hazeGlass(
input = HazeInput.Sources(hazeState),
style = GlassStyle.regular.then {
tint(Color.White.copy(alpha = 0.16f))
shape(RoundedCornerShape(20.dp))
},
)
.padding(24.dp)
) {
Column {
Text("玻璃拟态卡片", color = Color.White, fontSize = 20.sp)
Spacer(Modifier.height(8.dp))
Text("带折射感和高光的毛玻璃效果", color = Color.White.copy(0.8f))
}
}
}
}
GlassStyle.regular 提供了开箱即用的高质量默认参数,包含了折射模糊、物理高光与柔和阴影。若背景图色彩丰富且需要更高的通透度,可切换至 clear 变体,让底层纹理更清晰地透射出来。
性能调优策略
默认性能模式 HazePerformanceMode.Default 已针对主流设备做了自适应优化。绝大多数项目无需干预,但一旦在低端设备或复杂列表中遇到掉帧,可按照以下路径排查:
- 关闭 Debug 包测试:Debug 模式下 GPU 硬件加速受限,务必切换至 Release 包或 Benchmark 环境在真机验证。
- 动态调整性能档位:尝试切换至
Balanced(平衡模式)或Performance(流畅优先)。极端场景下可使用Fixed锁定模糊半径,牺牲画质换取绝对帧率。配合降采样机制,能进一步缓解长列表滚动时的渲染压力。 - 收缩源图层范围:
hazeSource捕获的像素面积直接决定计算开销。尽量精确控制被捕获区域,避免标记全屏冗余元素。 - CameraX 兼容方案:在实时相机预览上叠加模糊时,
PreviewView必须使用COMPATIBLE模式。原生SurfaceView由于渲染管线隔离,无法被上层捕获。
避坑指南与跨平台注意
- 版本号强制对齐:运行时依赖混用极易导致类找不到或渲染异常。
- Beta 期 API 波动:跨大版本升级前务必核对 Release Notes,部分参数签名可能调整。
- 多平台交付时,Gradle 插件的依赖解析需要特别注意。Android 端通常走
androidMain,而 iOS/Desktop/Web 走对应源码集。如果在commonMain中声明了完整依赖但编译报错,检查haze对应的 KMP 兼容性标记。对于 Wasm/JS 平台,由于浏览器的 Canvas 2D API 限制,复杂的实时模糊可能回退到静态渲染,建议在对应平台通过actual关键字提供轻量级降级实现。 - 多端视觉一致性:不同平台的栅格化引擎存在差异。iOS 的金属管线与 Android 的渲染器在边缘抗锯齿和高光混合算法上可能产生微小偏差,上线前需对各目标平台进行视觉走查。
总结
通过本教程,你掌握了利用 Haze 2 实现高级 UI 效果的完整链路:从模块化依赖配置,到「源-效果」分离架构的实际编码,再到性能调优与多平台验证。掌握了这些技巧,你可以轻松应对复杂的背景模糊、毛玻璃导航栏以及拟物化卡片需求。
建议前往官方 Sample 仓库探索更多高阶场景,例如对 LazyList 滚动区域的局部模糊处理。合理使用 Haze 能大幅缩减手写 Shader 和调试 Canvas 的时间成本,让你的 UI 评审更加顺利。