给Compose应用加毛玻璃:Haze三步出效果实战
【免费下载链接】hazeBackground blurring for Compose Multiplatform / Jetpack Compose项目地址: https://gitcode.com/gh_mirrors/ha/haze
想让顶部导航栏有毛玻璃质感,又不想手写 RenderEffect 和采样管线?Haze 是个 Compose 背景模糊库,一个 modifier 就能给内容加模糊,Android、iOS、Desktop、Web 四端可用。
❄️ 能力速览
Haze 2.0 把效果拆成了模块:用到什么拉什么,不用的不占体积。
| 维度 | 说明 |
|---|---|
| 平台 | Android(API 11+,13+ 走最优渲染路径)、Desktop (JVM)、iOS、Wasm/JS |
| 核心效果 | 背景模糊为主,可调 blurRadius、tint、noise,支持渐进式渐变与 mask |
| 许可 | Apache-2.0 |
| 现状 | 当前发布 2.0.0-alpha04,模块化新 API,alpha 阶段接口仍可能调整 |
- 模块划分:核心
haze只提供基础设施,模糊在haze-blur,预设材质在haze-blur-materials。只做模糊的话,至少拉前两个。 - 底层是按平台优化过的 Kotlin 背景模糊管线:Android 走 RenderNode,iOS/Desktop 走 Skia 着色器,全程硬件加速。
- 预设材质:
HazeMaterials/CupertinoMaterials/FluentMaterials三组,对应 Material、iOS、Windows 三种风格,都带明暗两套。
HazeMaterials 五种厚度的毛玻璃,明暗双主题
跑通第一个效果
加依赖、写一个 modifier、看效果,就三步。
第一步,在build.gradle.kts里加依赖:
dependencies { implementation("dev.chrisbanes.haze:haze:2.0.0-alpha04") implementation("dev.chrisbanes.haze:haze-blur:2.0.0-alpha04") }第二步,把内容包起来,叠一层模糊:
val hazeState = rememberHazeState() Box { Image( painter = painter, contentDescription = null, modifier = Modifier.hazeSource(hazeState), ) Box( modifier = Modifier.matchParentSize().hazeBlur( input = HazeInput.Sources(hazeState), style = HazeBlurStyle { blurRadius(20.dp) }, ), ) }第三步,看屏幕:下面的 Box 就是盖在图片上的 20dp 毛玻璃层。hazeSource标记模糊源,hazeBlur是效果落点,两者靠同一个hazeState关联,源内容变化时模糊实时跟随。
按场景实战
给顶部导航栏加毛玻璃
套路固定:滚动容器标 source,栏上贴模糊。
Box { LazyColumn(Modifier.fillMaxSize().hazeSource(hazeState)) { /* 可滚动内容 */ } TopAppBar( modifier = Modifier.hazeBlur( input = HazeInput.Sources(hazeState), style = HazeMaterials.thin(), ), ) }磨砂浮层压在正文上:背景可辨认但读不清,正是顶栏想要的层次
thin()的半径会透出背景轮廓,适合内容密集的列表页;想更实一点就换regular()或thick()。
给弹窗加毛玻璃背景
弹窗自身的 Surface 必须先用半透明色,否则不透明背景会挡住模糊要作用的对象。
Dialog(onDismissRequest = { showDialog = false }) { Surface(color = MaterialTheme.colorScheme.surface.copy(alpha = 0.2f)) { Box( modifier = Modifier.hazeBlur( input = HazeInput.Sources(hazeState), style = FluentMaterials.acrylicDefault(), ), ) } }FluentMaterials 的 acrylic 与 Mica 预设,桌面弹窗常用这套
同一份代码套在ModalBottomSheet内容上就是底部弹层效果,仓库示例里有现成写法可以直接抄。
⚙️ 进阶调参
两个参数决定观感和帧率:blurRadius与performanceMode。
- blurRadius:值越大越糊。20dp 时背景基本读不清,8dp 只留一点轮廓,超过 32dp 后肉眼差异很小,帧成本却明显上去。
- 预设是可重放的 Style,后写的生效:
HazeMaterials.thin().then { blurRadius(12.dp); noiseFactor(0f) }就能派生一个更薄、无颗粒感的版本,不用重写整套参数。 - performanceMode 默认
Adaptive自动调画质;背景持续滚动、帧预算紧张时再手动降档:
Modifier.hazeBlur( input = HazeInput.Sources(hazeState), style = style, performanceMode = HazePerformanceMode.Performance, )改完设置记得在真机上量一遍,有明确收益才保留覆盖。
⚠️ 避坑清单
| 现象 | 原因 | 解法 |
|---|---|---|
| Android 11 及以下毛玻璃变成一层半透明黑 | API 30 以下默认关闭模糊,回退为 scrim 遮罩 | Style 里写blurEnabled(true),启用实验性 RenderScript 路径 |
| 老设备上模糊慢一拍、有拖影 | RenderScript 路径在后台线程处理,会丢帧 | 缩小模糊区域(只给顶栏/弹层),或降 performanceMode |
| Android 12 上渐进式渐变开销大 | 12/12L 靠多次绘制实现 | preferPerformance = true回退到 mask 实现 |
Haze 适合需要一份毛玻璃代码跨四端复用的 Compose 项目,2.0 目前处于 alpha 阶段,API 还可能变,锁定版本号再上。细节看 docs/,顶栏、弹窗、底部弹层的可运行实现都在 sample/。
【免费下载链接】hazeBackground blurring for Compose Multiplatform / Jetpack Compose项目地址: https://gitcode.com/gh_mirrors/ha/haze
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考