跳到主内容
Apple
文章阅读

Liquid Glass 设计系统上手:iOS 26 / macOS Tahoe 的玻璃化 UI 应该怎么用

把 Liquid Glass 的设计原则、SwiftUI API、GlassEffectContainer、morphing 动画、工具栏集成、无障碍与已知坑整理成一份可直接上手的实践笔记。

2026/04/181448 次阅读9 分钟

Apple 在 WWDC 2025 推出的 Liquid Glass,不只是把毛玻璃做得更亮一点,而是把系统级材质、层级、动效和交互统一成了一套新的视觉语言。

如果你在做 iOS 26 / macOS Tahoe 的 SwiftUI 应用,这套设计最重要的不是“怎么把界面做得像玻璃”,而是要先理解它为什么存在:内容沉到底层,导航和控制浮到上层

这篇文章不是逐段翻译文档,而是把 liquid-glass-design 这个技能里的重点压缩成一份更适合开发者快速上手的实践笔记。

Liquid Glass 到底是什么

Liquid Glass 的核心特征可以概括成五个词:

  • 透光
  • 折射
  • 高光响应
  • 背景自适应
  • 状态形变

它和传统的模糊材质最大的区别在于,Liquid Glass 强调的是一种“有厚度、有动态反馈”的材质感:

  • 背景内容会产生轻微的 lensing(透镜感)
  • 设备或界面发生运动时,会出现 specular highlights(高光反射)
  • 颜色会受到背后内容影响,而不是一块固定的半透明灰色
  • 不同 UI 状态之间可以顺滑 morph,而不是生硬切换

所以它不是单一视觉效果,而是一整套系统材质 + 交互语言

最重要的设计原则

Liquid Glass 最值得记住的一条规则只有一句话:

玻璃应该用在导航和控件上,不应该盖在内容本身上。

也就是说,下面这些场景适合用玻璃:

  • 工具栏
  • Tab Bar
  • 浮动按钮
  • 筛选器
  • 轻量控制面板
  • 状态切换按钮组

下面这些场景不适合直接上玻璃:

  • 文章卡片
  • 长文本容器
  • 列表主体
  • 内容区背景
  • 大面积信息承载组件

Apple 想建立的是一种稳定的视觉层级:内容是地基,玻璃是漂浮层。如果你把内容卡片、正文容器、表单主体全做成玻璃,视觉层次会塌掉,界面也会变得很吵。

三种 Glass 形态

1. Regular Glass

默认款,也是最常用的一种。


Button("Action") {
    performAction()
}
.buttonStyle(.glass)

它会自动适配明暗环境,能吸收背景色,适合绝大多数控制类元素。

2. Clear Glass

更通透、存在感更弱。


Button("Subtle Action") {
    performAction()
}
.buttonStyle(.glassClear)

这类样式更容易受背景干扰,所以通常需要你对背景对比度更敏感。

3. Identity

相当于不加玻璃效果,用来做对照或者局部退出。


.glassEffect(.identity)

一个必须遵守的规则

不要在同一套界面里混用 Regular Glass 和 Clear Glass。

这是 Liquid Glass 里非常关键的一条视觉一致性规则。不要出现左边一个 .glass,右边一个 .glassClear 的情况,不然整个层级关系会立刻变得不稳定。

SwiftUI 里最常用的 API

基础用法


View()
    .glassEffect()

View()
    .glassEffect(in: RoundedRectangle(cornerRadius: 16))

View()
    .glassEffect(.regular, in: Capsule())

View()
    .glassEffect(in: Circle(), isEnabled: showGlass)

对应签名大致是这样:


func glassEffect(
    _ glass: Glass = .regular,
    in shape: some Shape = .rect,
    isEnabled: Bool = true
) -> some View

给玻璃加 tint


Button("Tinted") { }
    .buttonStyle(.glass)
    .tint(.blue)

interactive 交互型玻璃


View()
    .glassEffect(.regular.interactive(), in: Capsule())

常见按钮样式


Button("Glass") { }
    .buttonStyle(.glass)

Button("Prominent") { }
    .buttonStyle(.glassProminent)

Button("Borderless") { }
    .buttonStyle(.glassBorderless)

如果你只是做一个普通的按钮或操作入口,优先考虑 .buttonStyle(.glass),先别急着上更重的视觉变体。

GlassEffectContainer 才是进阶重点

很多人第一眼只会注意 .glassEffect(),但真正能把 Liquid Glass 用出系统感的,是 GlassEffectContainer

它的作用不是“包一层玻璃背景”,而是让多个玻璃元素共享同一套融合、模糊和形变逻辑。


GlassEffectContainer {
    HStack {
        Button("First") { }
            .glassEffect(in: Capsule())

        Button("Second") { }
            .glassEffect(in: Capsule())

        Button("Third") { }
            .glassEffect(in: Capsule())
    }
}

spacing 的意义


GlassEffectContainer(spacing: 8) {
    HStack(spacing: 4) {
        Button("A") { }
            .glassEffect(in: Capsule())
        Button("B") { }
            .glassEffect(in: Capsule())
    }
}

如果子元素之间的距离小于容器设定的 spacing 阈值,这些玻璃形状会更容易视觉融合;如果距离更大,它们就会保持独立。

这意味着 GlassEffectContainer 更像一个“玻璃行为域”,而不是一个普通布局容器。

Morphing 动画怎么做

Liquid Glass 很强的一点,是能把相关状态之间的切换做成更自然的形变。

glassEffectID 关联两个状态


@Namespace private var animation

Button("Collapsed") { }
    .glassEffect(in: Capsule())
    .glassEffectID("button", in: animation)

Button("Expanded") { }
    .glassEffect(in: Capsule())
    .glassEffectID("button", in: animation)

同一个 glassEffectID 可以告诉系统:这两个控件在视觉上是同一个角色,只是状态变了,所以请用 morphing 过渡,而不是把旧元素消失、新元素出现。

控制出现与消失的方式


View()
    .glassEffect(in: Capsule())
    .glassEffectTransition(.scale, isEnabled: true)

常见可选值包括:

  • .opacity
  • .scale
  • .slide
  • .identity

如果你的状态变化本来就有明确主次关系,Liquid Glass 的形变动画会比普通的 opacity + offset 更有系统感。

工具栏、导航和 Tab Bar 会是主战场

在 iOS 26 里,工具栏和导航系统本身就会天然贴近 Liquid Glass 语言,所以你最应该把精力花在这些位置,而不是给页面中间的大卡片乱加玻璃。

工具栏分组


.toolbar {
    ToolbarItem(placement: .primaryAction) {
        Button("Save") { }
    }

    ToolbarSpacer(.fixed)

    ToolbarItem(placement: .secondaryAction) {
        Button("Share") { }
    }
}

ToolbarSpacer(.fixed) 的价值很直接:它能明确划分一组主操作和一组次操作,让玻璃层的结构更清楚。

关闭按钮角色


.toolbar {
    ToolbarItem(placement: .cancellationAction) {
        Button("Close", role: .close) {
            dismiss()
        }
    }
}

role: .close 会更贴近系统的关闭按钮语义和样式。

搜索 Tab


TabView {
    SearchView()
        .tabItem {
            Label("Search", systemImage: "magnifyingglass")
        }
        .tab(role: .search)
}

这里的 tab(role: .search) 也体现了 Liquid Glass 的一个核心思路:不是把组件静态摆在那里,而是让它在不同任务态之间自然过渡。

无障碍不是补丁,而是默认约束

Liquid Glass 会自动尊重系统无障碍设置,这一点非常重要。

Reduce Transparency

开启后,玻璃会更偏磨砂、更不透明,以保证阅读对比度。


@Environment(\.accessibilityReduceTransparency) var reduceTransparency

Increase Contrast

开启后,整体会更偏黑白高对比,边界也会更清晰。


@Environment(\.colorSchemeContrast) var contrast

Reduce Motion

如果用户开启减少动态效果,玻璃的 morphing 和过渡应该跟着收敛。


@Environment(\.accessibilityReduceMotion) var reduceMotion

withAnimation(reduceMotion ? .none : .spring) {
    state.toggle()
}

这不是锦上添花,而是你在做 Liquid Glass 时必须默认纳入的交互约束。

一个当前已知坑

根据当前资料,iOS 26.1 中把 Menu 放进 GlassEffectContainer 会破坏 morphing 动画

也就是说,下面这种写法要避免:


GlassEffectContainer {
    Menu("Options") {
        Button("Edit") { }
        Button("Delete") { }
    }
    .glassEffect(in: Capsule())
}

更稳妥的做法,是把 Menu 拿到容器外面,让容器只负责那些真的需要共享玻璃行为的元素。

我建议你在项目里这样落地

如果你要把 Liquid Glass 用进真实应用,我建议按这个顺序推进:

  1. 先只在工具栏、浮动操作按钮、Tab Bar 邻近控件里使用玻璃。
  2. 再把一个最核心的状态切换,改成 GlassEffectContainer + glassEffectID
  3. 最后再测试 Reduce Transparency、Increase Contrast、Reduce Motion 三组无障碍场景。

而不是一上来就把整个页面都玻璃化。

一份足够实用的检查清单

在进入开发前,你至少应该确认下面这些点:

  • 玻璃是否只用于导航和控制,而不是内容主体
  • 同一套界面里有没有混用 .glass.glassClear
  • 相关状态切换是否值得用 glassEffectID 做形变衔接
  • 是否已经验证 Reduce Transparency 和 Reduce Motion
  • 是否出现 glass-on-glass 的嵌套层叠
  • GlassEffectContainer 的范围是否只包住真正有关联的一组控件

结语

Liquid Glass 最容易让人误解的地方,是大家会先把它当成“新的视觉特效”。

但如果只把它当成玻璃滤镜,你做出来的 UI 往往会很快变廉价。它真正的价值其实在于:重新定义内容、控制、导航、状态变化之间的层级关系。

如果你在做 iOS 26 / macOS Tahoe 的新项目,最值得优先学习的不是如何把所有 View 都套上 .glassEffect(),而是先想清楚哪些元素应该漂浮、哪些元素必须沉稳。

只有这一步对了,Liquid Glass 才会看起来像系统设计,而不是装饰。

返回顶部