返回博客

iOS 26 Liquid Glass:层次感的克制与组织

iOS 26 带来了 Liquid Glass——一种会模糊身后内容、从周围环境反射颜色和光线、还能对触摸做出形变反应的动态材质。苹果这次把它做进了 SwiftUI、UIKit 和 WidgetKit,API 设计相当克制,但「克制」本身就是一个需要花时间理解的原则。

我踩过的第一个弯路是:看到 .glassEffect() 这么好用,一不小心往每个卡片、每个 label 上都加了一遍。结果页面变成一锅毛玻璃粥——没有主次,反而失去了深度感。Liquid Glass 的价值在于选择性,把它留给真正需要浮于内容之上的元素。

三件事决定玻璃效果是否到位

第一件事:Container 不能省。 当页面里有两个以上相邻的 glass view 时,务必把它们套进 GlassEffectContainer

GlassEffectContainer(spacing: 40.0) {
    HStack(spacing: 40.0) {
        Image(systemName: "scribble.variable")
            .frame(width: 80, height: 80)
            .glassEffect()
        Image(systemName: "eraser.fill")
            .frame(width: 80, height: 80)
            .glassEffect()
    }
}

spacing 参数控制「融合距离」——两个 glass 元素靠得足够近时,它们的轮廓会自然地流体合并。不用 Container 就失去了这个行为,每个元素各自独立渲染,性能也更差。

第二件事:morphing 需要 namespace 配合。 玻璃元素出现或消失时,想要平滑的形变动画,需要给每个元素声明身份:

@Namespace private var glassSpace
 
Image(systemName: "pencil")
    .glassEffect()
    .glassEffectID("pencil", in: glassSpace)

再配合 withAnimation { isExpanded.toggle() } 触发状态切换,系统就知道该对哪两个形状做插值过渡。少了 glassEffectID,出现消失只是普通的 opacity 动画,完全没有 Liquid Glass 的流体质感。

第三件事:.interactive() 要显式开启。 不是每块玻璃都应该对触摸作出反应——静态的背景卡片不需要,工具栏按钮才需要。interactive() 是明确的 opt-in:

Button("操作") { }
    .buttonStyle(.glass)  // 内置样式已包含 interactive
 
// 或者手动:
.glassEffect(.regular.tint(.orange).interactive(), in: .rect(cornerRadius: 16))
用量克制才有深度

Liquid Glass 不是装饰手段,是「层次语言」。只给真正浮在内容上层的元素加玻璃效果:导航栏、工具栏、浮动按钮、卡片容器。背景、文字、图表——不加。

Widget 的特殊处理

在 WidgetKit 里,还需要应对一个额外维度:用户可能开启了「着色主屏」,系统会把 widget 渲染成单色玻璃模式。忘记处理这个分支,就会在某些主屏主题下出现视觉错乱:

@Environment(\.widgetRenderingMode) var renderingMode
 
var body: some View {
    if renderingMode == .accented {
        // 着色模式:只保留结构,颜色让系统接管
    } else {
        // 正常全彩模式
    }
}

对需要在着色模式下保持清晰的图片,加 .widgetAccentedRenderingMode(.monochrome) 让系统统一处理色调。

反模式速查

  • 不用 Container 直接堆多个 glass:失去形变合并,性能下降
  • 对每个视图都加 glass:视觉噪声,层次感消失
  • UIKit 里忘了 clipsToBounds = true:圆角不生效,玻璃溢出父视图
  • 背景用不透明色:遮住了模糊层,glass 效果等于零
  • Widget 不处理 accented 模式:着色主屏下外观破坏

一句话心法

玻璃是层次的语言,不是装饰的手段——每多加一块,就多问一次「它真的浮在内容上方吗?」