← 所有文章

SwiftUI 中的 Liquid Glass:在 iOS 26 上交付 Return 总结的三种模式

苹果的 Liquid Glass 是一行 SwiftUI API:.glassEffect()1 我的冥想计时器 Return 在 iOS、macOS 和 tvOS 上一共使用了它九次。2 其中一次将这个修饰符应用到一个自定义 Shape 上,把计时器的数字本身逐个字形地变成了 Liquid Glass。

iPhone 上的 Return —— 计时器数字本身通过自定义 Shape 渲染为 Liquid Glass(下文模式 1 中介绍);时长选择器是一个 Liquid Glass HUD

有意思的问题是:当你超越这一行代码之后会发生什么。苹果的 Human Interface Guidelines 给出了一条严格的分层规则:Liquid Glass 属于功能层(控件、导航、瞬态 UI),绝不属于内容层。3 Return 的九处用法大多是教科书式的功能层应用:选择器、按钮、控制条、暂停状态徽标。真正有意思的是其中三处——它们弯曲了规则却没有打破它。

本文将逐一讲解我交付的三种模式、它们所遵循的规则、绊倒我的那些陷阱,以及我有意没有使用的 API 表面。

苹果的 Human Interface Guidelines 通过三种材质变体来定义 Liquid Glass。regular 变体会根据其下方的内容调整外观(左例为深色,右例为浅色);clear 变体则让底层细节透出,过滤要少得多:3

深色背景上的 Liquid Glass regular 变体 —— 苹果 HIG 参考

浅色背景上的 Liquid Glass regular 变体 —— 苹果 HIG 参考

Liquid Glass clear 变体 —— 苹果 HIG 参考,展示 clear 变体如何让底层内容的视觉细节透出

参考图片来自苹果的 Materials HIG 页面3 这两种变体都是 .glassEffect() 在 SwiftUI 中所产生的效果;二者之间的选择只是修饰符上的一个参数。

TL;DR

  • iOS 26 将 Liquid Glass 作为 .glassEffect(_:in:) 发布。默认变体是 .regular,默认形状是 Capsule1
  • Return 使用了三种超越一行代码的模式:在自定义 Shape 上实现玻璃效果(通过 Core Text 字形路径处理计时器文本)、镜面模式(通过翻转并遮罩的副本在下方实现倒影),以及功能层的 HUD 叠层。
  • 苹果的 HIG 规则:Liquid Glass 用于功能层,标准材质用于内容层。3
  • 我有意没有使用 GlassEffectContainer。它的形变 API 在 Return 中没有用武之地(没有任何玻璃元素需要变形为另一个),而且我也没有对渲染性能差距做过基准测试;这是一个未经测量的权衡,而非一项推荐做法。1
  • 陷阱:平面背景上的玻璃看起来就是扁平的;无抖动的数字渲染需要固定宽度的单元格;tvOS 的 HStack 会忽略布局方向环境值;形变动画必须尊重减弱动态效果设置。

关于相邻的苹果 UI 模式,可阅读 SwiftUI 布局协议深度剖析SF Pro 排版系统以及 Symbol Effects 词汇表

一行 API 与分层规则

苹果以一个很小的表面积发布了 Liquid Glass,并在 WWDC 2025 上将其作为一大设计支柱推出:113

Text("Hello, World!")
    .font(.title)
    .padding()
    .glassEffect()                              // default: .regular variant, Capsule shape

Text("Hello, World!")
    .glassEffect(in: .rect(cornerRadius: 16))   // custom shape

Text("Hello, World!")
    .glassEffect(.regular.tint(.orange).interactive())  // tint + touch reactivity

三个旋钮:变体(.regular.clear)、形状(任意 Shape)以及一条 GlassEffectStyle 链(着色、interactive)。这就是单个视图的全部 API。多视图渲染由单独的 GlassEffectContainer 处理,后文会讲到。

HIG 比 API 更为严格。苹果的 Human Interface Guidelines 在每个 iOS 26+ 界面中定义了两个层:3

  1. 内容层: 人们正在消费的文档、列表、照片或媒体。这里使用标准材质(现有的 .regularMaterial.thinMaterial 等)。
  2. 功能层: 控件、导航、标签栏、侧边栏、瞬态叠层。这里使用 Liquid Glass

苹果的具体指示是:“不要在内容层使用 Liquid Glass。当 Liquid Glass 能在交互元素与内容之间提供清晰区分时效果最佳;将其纳入内容层会导致不必要的复杂性和令人困惑的视觉层次。”3

这条规则听起来限制很大,直到你把它映射到一个真实的应用上。Return 是一个冥想计时器。它的内容层是呼吸意象以及在所有元素背后循环播放的视频。它的功能层是时长选择器、开始/暂停/停止按钮组、次级设置按钮行,以及(在 tvOS 上)暂停状态徽标。Return 九处玻璃用法中有八处是教科书式的功能层应用:iOS 与 macOS 代码路径的三种时长选择器变体、开始/暂停切换、停止按钮、设置按钮行、tvOS 暂停指示器,以及另外一个瞬态控制叠层。4

第九处是有意为之的边界情况(在计时器数字本身上使用 Liquid Glass),下一节会详细讲解。

模式 1:自定义形状上的玻璃效果

Return 中的计时器数字并不是画在玻璃背景之上的文本。玻璃就是文本本身。.glassEffect(.clear, in:) 接受任意 Shape9Shape 是一个生成 Path 的协议。10 所以诀窍在于:用 Core Text 把计时器字符串转换成一条字形路径,11 然后把这条”路径即形状”传给 .glassEffect56

import SwiftUI
@preconcurrency import CoreText

struct GlassTextShape: Shape {
    let text: String
    let font: CTFont

    func path(in rect: CGRect) -> Path {
        guard !text.isEmpty else { return Path() }
        let combinedPath = CGMutablePath()

        let attrString = NSAttributedString(string: text, attributes: [.font: font])
        let line = CTLineCreateWithAttributedString(attrString)
        guard let runs = CTLineGetGlyphRuns(line) as? [CTRun], !runs.isEmpty else {
            return Path()
        }

        for run in runs {
            let glyphCount = CTRunGetGlyphCount(run)
            guard glyphCount > 0 else { continue }
            var glyphs = [CGGlyph](repeating: 0, count: glyphCount)
            var positions = [CGPoint](repeating: .zero, count: glyphCount)
            let range = CFRange(location: 0, length: glyphCount)
            CTRunGetGlyphs(run, range, &glyphs)
            CTRunGetPositions(run, range, &positions)

            for i in 0..<glyphCount {
                guard let glyphPath = CTFontCreatePathForGlyph(font, glyphs[i], nil) else { continue }
                let transform = CGAffineTransform(translationX: positions[i].x, y: positions[i].y)
                combinedPath.addPath(glyphPath, transform: transform)
            }
        }

        // Core Text y-axis is flipped vs SwiftUI; flip then re-bound and center.
        var swiftPath = Path(combinedPath).applying(CGAffineTransform(scaleX: 1, y: -1))
        let flippedBounds = swiftPath.boundingRect
        let offsetX = rect.midX - flippedBounds.midX
        let offsetY = rect.midY - flippedBounds.midY
        return swiftPath.applying(CGAffineTransform(translationX: offsetX, y: offsetY))
    }
}

来自 Return/Return/GlassTextShape.swift 的真实生产代码。5 path(in:) 函数用 Core Text 对字符串进行排版,遍历每一个 CTRun,提取每个字形的 CGPath,并把它们合并到一个 CGMutablePath 中。合并之后有两个不那么显而易见的步骤:Core Text 的坐标系把原点放在左下角,而 SwiftUI 的 Path 把原点放在左上角,因此必须通过 CGAffineTransform(scaleX: 1, y: -1) 翻转这条路径。然后翻转后路径的 boundingRect 会带有负的 y 值,所以需要一次平移把它在 SwiftUI 交给 Shape 的矩形内重新居中。少做任何一次变换,字形都会渲染成上下颠倒或跑到屏幕之外。

接着,应用就是一行代码:

Rectangle()
    .fill(.clear)
    .glassEffect(.clear, in: textShape)
    .frame(width: cellWidth, height: cellHeight)

这个透明的 Rectangle 是一个命中目标占位符;实际的视觉效果取决于 textShape 所产生的形状。配上字形路径形状后,Liquid Glass 材质只填充字形轮廓。结果就是:计时器的每个数字都是一个独立的 Liquid Glass 形态,折射在其背后运行的任何动画。6

HIG 的微妙之处。 苹果明确给出的规则是 Liquid Glass 用于功能层,标准材质用于内容层,并有一个明确的例外:内容层中的瞬态交互控件(滑块、开关)在被激活时可以采用 Liquid Glass。3 Return 中的计时器数字是状态显示,而非控件:它们由 Timer.publish(every: 1, ...) 每秒更新一次,且没有任何点按手势(切换状态的是它们下方的开始/暂停按钮)。所以在它们上面使用 Liquid Glass 是一个有意为之的边界情况,从意图上看它更接近”瞬态交互控件”,而非字面意义上的交互性——因为这些数字是用户整段会话都在注视的视觉焦点。我是在弯曲规则,而非打破它。一位严格依据 HIG 阅读的评审者可能会主张这里应该用标准材质;而我主张计时器是一种时间流逝控制面,与进度指示器属于同一族类。苹果的文档并未直接对这一情况做出裁决。

为什么用自定义 Shape 而非 Text + 背景。 渲染在玻璃背景之上的 Text 读起来是玻璃上的文本。而渲染为玻璃本身Text 读起来是另一种视觉类别。用户会把这些数字感知为功能性的前景,具体而言是一个供人透过去看、而非看其本身的瞬态元素。

模式 2:镜面模式

Return 在计时器下方显示其倒影,并逐渐淡出。真实生产代码:6

Mac 上的 Return —— 时长选择器作为 Liquid Glass HUD 叠层,上方可见计时器文本的玻璃处理

VStack(spacing: 0) {
    GlassTimerText(text: displayTime, fontSize: fontSize)
        .accessibilityLabel("Time remaining: \(accessibleDescription)")

    if showReflection {
        GlassTimerText(text: displayTime, fontSize: fontSize)
            .scaleEffect(x: 1, y: -1)
            .mask(
                LinearGradient(
                    stops: [
                        .init(color: .white.opacity(0.2), location: 0),
                        .init(color: .clear, location: 0.6)
                    ],
                    startPoint: .top,
                    endPoint: .bottom
                )
            )
            .offset(y: -8)
            .accessibilityHidden(true)
    }
}

三个变换组合出这个镜面效果,全部是标准的 SwiftUI 原语:14

  1. scaleEffect(x: 1, y: -1) 把第二个副本上下翻转。
  2. .mask(LinearGradient(...)) 让倒影从顶部 20% 不透明度淡出到 60% 处完全透明。
  3. .offset(y: -8) 把倒影向上拉 8 个点,使其紧贴原件,而不会留下可见的接缝。

倒影上的 .accessibilityHidden(true) 修饰符至关重要。VoiceOver 不应该把镜像的时间念两遍;原件的 accessibilityLabelaccessibilityAddTraits(.updatesFrequently) 已经附加到上方主 GlassTimerText 实例上,而倒影纯粹是装饰性的。

为什么这一招专门对 Liquid Glass 奏效。 倒影继承了 GlassTimerText 的玻璃材质。原件所处的任何背景(呼吸圆圈渐变、视频、带色调的场景)都会透过这两个副本折射。镜面效果不需要任何玻璃专属代码;玻璃材质免费处理了折射。整个效果就是三个修饰符加一个渐变。

无障碍代价。 开启减弱动态效果的用户仍会看到镜面,但玻璃材质在时间更新之间的动画已通过 @Environment(\.accessibilityReduceMotion) 在别处被抑制。7 倒影本身是静态的;只有数字过渡之间的形变才会产生动画。

模式 3:用于瞬态控件的玻璃 HUD 叠层

Return 中余下的八处玻璃用法都是教科书式的功能层应用。4 每一处都遵循相同的模式:

Apple Watch 上的 Return —— 在小画布尺寸下的功能层 Liquid Glass

durationPicker
    .frame(height: 50)
    .frame(maxWidth: 320)
    .glassEffect()
    .padding(.horizontal, 20)
    .transition(.opacity.combined(with: .scale(scale: 0.95)))

.transition(.opacity.combined(with: .scale(scale: 0.95))) 是其中至关重要的部分。瞬态控件上的 Liquid Glass 只有在控件进出时才感觉对。一个永久停留在屏幕上的静态玻璃 HUD 读起来像是边框装饰。而一个在用户点按时淡入并缩放进入、在用户移开视线时退出的玻璃 HUD,读起来则像是一个临时的控制面。

苹果关于 glassEffect 的文档隐含地指出了这一点:该修饰符会”捕获内容以发送给容器进行渲染”,并”实时对触摸和指针交互做出反应”。1 API 中没有动画钩子,但渲染管线假定玻璃元素会移动。静态玻璃元素错失了这种可供性。

Return 在以下场景使用了这一模式:时长选择器(用户点按时向上滑出)、开始/暂停切换按钮(始终可见但按下时缩放)、停止按钮(仅在会话进行中可见)、设置按钮行(时长选择器下方的一条水平控制条),以及 tvOS 暂停状态徽标(仅当 Apple TV 上的会话被暂停时可见)。这五种语境都尊重 HIG 的功能层规则。3

苹果的 tvOS 参考:Liquid Glass 叠层浮于视频背景之上,让底层媒体透出 —— 经典的 10 英尺 UI 用例

苹果 HIG 参考:tvOS 中的 Liquid Glass 叠层位于媒体层之上,让媒体透出。3 Return 的 tvOS 实现遵循同一模型:控件浮于循环播放的火焰/森林/水流背景之上。

来自实验室的一条工具栏说明。 一场 WWDC 2026 SwiftUI Group Lab 座谈把这一点在工具栏中的呈现讲得更透彻。在工具栏中放置非玻璃内容(示例是一张个人头像)需要用 sharedBackgroundVisibility(.hidden),这样该项目会去掉其共享的玻璃背景并直接显示头像。15 座谈还点出了一处改进:一个较新的 API 仅移除工具栏按钮的内容外边距,而此前隐藏背景是唯一的手段,它会把背景和外边距一起移除。对于工具栏按钮本身,座谈倾向于使用醒目按钮样式(glassProminent)和 buttonBorderShape,而不是直接在按钮上动用 .glassEffect。其背后的 HIG 立场正是本文所依托的那条分层规则:Liquid Glass 属于边框装饰,而非内容区域,因为一个底下没有内容滚动经过的玻璃表面没有任何东西可供折射。153

GlassEffectContainer 的问题

每当应用在多个视图上使用 .glassEffect() 时,苹果都推荐使用 GlassEffectContainer,原因有二:更好的渲染性能(玻璃效果会被批处理)以及在过渡期间将形状变形为彼此的能力。1

我没有用它。这个理由是针对具体应用的,并非对苹果指引的反驳。Return 有九个玻璃视图,没有一个需要彼此之间变形。46 时长选择器从不会动画变形为开始按钮。计时器文本从不会动画变形为设置按钮行。每个玻璃元素都是独立的。变形 API 没有任何用例可供触发,而容器的间距规则反而会约束今天根本不需要协调的布局。

渲染性能这一论点,我在没有测量的情况下无法完全反驳。苹果的文档警告说,在容器之外有”太多”玻璃效果会降低性能。1 Return 的九个视图从不会同时出现在屏幕上(时长选择器只在菜单状态出现,停止按钮只在会话进行中暂停时出现)。在任意给定帧上,我数到的可见玻璃元素是三到四个,这在我跨 iOS、iPadOS、macOS、watchOS 和 tvOS 测试过的每一台设备上都很流畅,但我并没有用 Instruments 跑过对比容器包裹与仅用修饰符两种情况的追踪。所以诚实的表述是:Return 跳过 GlassEffectContainer,依据的是观察到的良好用户体验,而非经过测量的性能等价性。

我从中得出的规则是:GlassEffectContainer 适用于那些多个玻璃元素同时可见并产生动画的应用。 苹果的示例是用 glassEffectUnion(id:namespace:) 进行的符号集渲染:四个天气符号像一个整体一样流畅地合并与拆分。1 这是一个教科书式的用例。如果将来 Return 的某个功能需要玻璃元素变形或共享容器的间距规则,那时再加上容器才是正确的工具。对于今天的应用,我还没有遇到这种情况。

绊倒我的那些陷阱

来自生产环境的三个真实 bug:

玻璃数字抖动。 SF Pro Rounded 在比例渲染下具有可变宽度的数字。随着计时器倒数,显示的字符串长度发生变化,周围的 HStack 每秒都会重排,使整个计时器抖动。修复办法:为每个字符使用固定宽度的单元格。每个数字获得 fontSize * 0.6cellWidth,每个冒号获得 fontSize * 0.3,于是 HStack 变成了一个稳定的网格。6

HStack(spacing: 0) {
    ForEach(Array(text.enumerated()), id: \.offset) { _, char in
        let isColon = char == ":"
        let cellWidth = isColon ? colonCellWidth : digitCellWidth
        GlassDigitCell(character: String(char), font: ctFont,
                       cellWidth: cellWidth, cellHeight: cellHeight)
    }
}

这些单元格并非苹果标准做法;它们是针对小型固定字号下比例宽度渲染的变通方案。苹果的 SF Pro Rounded 配合 .monospacedDigit() 能在 Text 上解决同样的问题,但这个修饰符在基于自定义 Shape 的玻璃渲染器上不可用。固定单元格布局就是它的替代品。

tvOS 布局方向覆盖。 同一个 GlassTimerText 在 iOS、iPadOS、macOS 和 tvOS 上运行。唯独在 tvOS 上,HStack 会在从右到左的语言环境下镜像,即便 iOS 版本尊重环境内的覆盖设置。修复办法:同时通过环境值和显式的 flipsForRightToLeftLayoutDirection(false) 修饰符来固定布局方向,并直接应用到数字单元格的 HStack 上(父级 VStack 单独应用环境覆盖,以便倒影副本继承它):6

HStack(spacing: 0) { ... }
    .flipsForRightToLeftLayoutDirection(false)
    .environment(\.layoutDirection, .leftToRight)

原因在于:tvOS 的 HStack 似乎在某些版本中会忽略环境级别的覆盖,而 flipsForRightToLeftLayoutDirection(false) 是一份明确的”不镜像”契约,被更可靠地尊重。12 双保险。

数字形变上的减弱动态效果。 Liquid Glass 默认会在显示的字符串之间产生形变过渡动画。开启了 accessibilityReduceMotion 的用户会把这种形变看成闪烁。修复办法:6

.animation(reduceMotion ? nil : .easeInOut(duration: 0.15), value: displayTime)

这个动画修饰符读取 @Environment(\.accessibilityReduceMotion),并在开启减弱动态效果时彻底禁用过渡。苹果的无障碍指引说得很明确:任何装饰性动画都必须尊重用户的动态偏好。7

何时不该使用 Liquid Glass

拒绝也是设计的一部分。

不要在内容层使用 Liquid Glass。 苹果的 HIG 说得很明确,无视这条规则会产生令人困惑的层次:用户无法分辨什么是可交互的、什么是内容。3 如果玻璃效果在装饰一个列表行或一张照片卡片,那这个设计就是在与平台对抗。

不要在平面背景上使用玻璃。 Liquid Glass 折射其背后的内容。如果”其背后的内容”是单一的纯色,折射就没有任何东西可弯曲,结果读起来就是一个扁平的带色调矩形。要么把玻璃放在变化丰富的内容之上(渐变、图像、视频),要么干脆不用玻璃。Return 的计时器屏幕通过 VideoBackgroundView 运行基于主题的封面意象和循环视频作为背景,4 正是为了让其上方的玻璃元素始终有纹理可供折射。

对高频内容上的玻璃要谨慎。 玻璃材质渲染受 GPU 约束,而玻璃形状变化之间默认的形变动画本身也是一种动画。在我的测试中,每秒更新一次的计时器没问题;以 60 Hz 运行的波形图或音频可视化效果则未经验证,且很可能会与形变动画冲突。我并没有对其上限做过基准测试;请把这当作经验法则,而非经过测量的阈值。苹果的文档也没有公布一个数值。

不要在没测试减弱动态效果的情况下交付玻璃。 每个玻璃动画都应该以 accessibilityReduceMotion 为门控。7 玻璃形状之间默认的形变是一种动态效果,而不仅仅是淡入淡出。

对在 iOS 26+ 上交付的应用而言,Liquid Glass 意味着什么

这个论点很小。只有当应用已经尊重 HIG 分层规则时,Liquid Glass 才是一行 API。 一个把控件放在功能层、把内容放在内容层的 SwiftUI 应用,可以用 .glassEffect() 修饰符采用 Liquid Glass,并默认就感觉很原生。

把两层混在一起的应用(控件塞进列表行、把导航栏当作内容对待、照片卡片上的装饰性边框)采用 Liquid Glass 后会感觉不对劲。材质是对的;它之下的架构不对。

自定义 Shape 模式(模式 1)干净利落地扩展了这条规则。任何在功能上属于控件的东西都可以采用 Liquid Glass,即便它看起来不像传统意义上的”控件”。计时器是一种控件,电平表是一种控件,进度指示器是一种控件。在这些东西上使用 Liquid Glass 都是合乎规范的。

把本文与我此前关于通过 App Intents 以及通过 MCP 服务器 交付同一应用数据层的文章结合起来读。视觉层是同一技术栈的第三个表面:为系统 AI 准备的类型化实体、为跨 LLM 智能体准备的文件格式,以及为设备前的人准备的 Liquid Glass。8

FAQ

我能在非 iOS 26 平台上使用 .glassEffect() 吗?

.glassEffect() 修饰符需要 iOS 26+、iPadOS 26+、macOS 26+、watchOS 26+、tvOS 26+、visionOS 26+。26 之前的平台有 .background(.regularMaterial) 及类似手段,它们能产生磨砂玻璃效果,但没有新的 Liquid Glass 折射。1

GlassEffectContainer 会改变视觉效果吗?

被容器包裹的玻璃元素可以在它们的间距规则导致重叠时把各自的形状融合在一起。没有容器时,每个 .glassEffect() 都是独立的。对于玻璃元素应在动画期间流畅合并的应用,GlassEffectContainer 是正确的工具。对于每个玻璃元素保持各自独立的应用,容器是一种额外开销。1

为什么不直接用 Text.foregroundStyle(.thinMaterial)

thinMaterial 是一种标准材质,不是 Liquid Glass。其视觉效果是磨砂玻璃叠层,而非 Liquid Glass 那种带光线弯曲的折射玻璃效果。3 对于应当专门呈现新材质外观的文本,.glassEffect(.clear, in: customShape) 才是受支持的路径。

我该如何为营销捕获一张 Liquid Glass 截图?

玻璃效果是在运行时由 GPU 渲染的,所以截图要在效果已经应用的状态下从模拟器或设备上获取。苹果官方的 Liquid Glass 参考图像来自其 HIG 文档页面以及 WWDC 2025 的会议。3

GlassTextShape 对任意文本都管用,还是只对数字管用?

任何 Core Text 能排版的字符串都管用。Return 把它用于数字和一个冒号,但同一个 Shape 对字母、符号、emoji(配合合适的字体)或混合字符串同样有效。性能受字形数量的限制;把一长段文字渲染为玻璃会很昂贵,但一个六字符的计时器则微不足道。


三种模式、一条规则,以及一个我有意跳过的 API。Liquid Glass 是 iOS 26+ 应用的第三个表面,位于类型化实体和共享文件格式之上。这一行 API 是真实存在的。而让这一行代码奏效的,是它之下的那条 HIG 规则。

References


  1. Apple Developer, “Applying Liquid Glass to custom views”. Documentation for the glassEffect(_:in:) modifier, GlassEffectContainer, glassEffectUnion(id:namespace:), glassEffectID(_:in:), and GlassEffectTransition. Default variant .regular, default shape Capsule

  2. Author’s Return, a meditation-timer app published on the App Store on April 21, 2026, available for iPhone, iPad, Mac, Apple Watch, and Apple TV. Uses SwiftUI, SwiftData, and HealthKit on iOS 26+ / macOS 26+. 

  3. Apple Developer, “Materials” Human Interface Guidelines. Defines the functional vs content layer rule for Liquid Glass: “Don’t use Liquid Glass in the content layer.” Lists the regular and clear variants and their intended uses. 

  4. Production code in Return/Return/ContentView.swift (seven .glassEffect() call sites), Return/Return/GlassTimerText.swift (one call site on GlassDigitCell), and Return/ReturnTV/TVContentView.swift (one call site on the tvOS “Paused” indicator). Total nine. Plus Return/Return/VideoBackgroundView.swift, which renders the theme-based cover imagery and looped video that the glass elements refract through. 

  5. Production code in Return/Return/GlassTextShape.swift. The Shape-conforming wrapper around Core Text. Created November 26, 2025, included in shipped App Store v1.0. 

  6. Production code in Return/Return/GlassTimerText.swift. GlassDigitCell, GlassTimerText, and GlassTimerDisplay views. Implements fixed-width cell layout, the mirror reflection, and reduce-motion gating. 

  7. Apple Developer, “accessibilityReduceMotion” environment value. Apps must honor the user’s motion preference; default morph animations on Liquid Glass should be gated on the value. 

  8. Author’s analysis in App Intents Are Apple’s New API to Your App and Two Agent Ecosystems, One Shopping List. The three-surface model: App Intents for Apple Intelligence, MCP for cross-LLM agents, Liquid Glass for the human at the device. 

  9. Apple Developer, “glassEffect(_:in:isEnabled:)” on View. The in: parameter accepts any Shape-conforming type. The default shape is Capsule

  10. Apple Developer, “Shape” protocol. A Shape is any type that produces a Path for a given rectangle. Custom shapes can wrap arbitrary CGPath data. 

  11. Apple Developer, “Core Text Programming Guide” and CTLineCreateWithAttributedString. Core Text is the lower-level text engine used to lay out attributed strings into glyph runs and extract per-glyph paths. 

  12. Apple Developer, “flipsForRightToLeftLayoutDirection(_:)”. Explicitly overrides RTL mirroring on a View regardless of the surrounding \.layoutDirection environment value. 

  13. Apple, “WWDC 2025 Highlights” via Apple Newsroom. Liquid Glass announced as the unifying design material across iOS 26, iPadOS 26, macOS 26, watchOS 26, tvOS 26, and visionOS 26. Sessions: “Meet Liquid Glass” (WWDC 2025), “Build a SwiftUI app with Liquid Glass”

  14. Apple Developer, “LinearGradient”, “scaleEffect(x:y:anchor:)”, “mask(_:)”. Standard SwiftUI primitives, all available since iOS 13. 

  15. Apple, WWDC 2026 SwiftUI Group Lab (session 2). Paraphrased from a locally transcribed recording of the WWDC 2026 SwiftUI Group Lab (session 2); Apple publishes no official captions for the labs. Source for hiding a toolbar item’s shared glass background to show non-glass content (a profile photo), the newer API that removes only a toolbar button’s content margin rather than the background and margin together, the preference for the prominent glass button style and buttonBorderShape over .glassEffect on a button, and the chrome-not-content layering rationale. The supporting symbols are documented at sharedBackgroundVisibility(_:) on CustomizableToolbarContent, which takes a Visibility value such as .hidden, and buttonBorderShape(_:); glassProminent is the prominent Liquid Glass PrimitiveButtonStyle. The specific content-margin API named in the lab could not be confirmed against Apple’s published documentation, so it is described by behavior rather than asserted by symbol. 

相关文章

iOS 26 上的 HealthKit + SwiftUI:来自两款已上架应用的授权流程、样本类型与跨平台模式

来自 Water(饮水追踪,HKQuantitySample)和 Return(正念会话,HKCategorySample)的真实生产模式。权限 UX、async 封装、watchOS 变体,以及需要避开的陷阱。

5 分钟阅读

SwiftUI Layout 协议:从 sizeThatFits 到 placeSubviews 构建自定义布局

iOS 16 的 Layout 协议让应用可通过两个方法构建自定义布局。sizeThatFits、placeSubviews、proposal 契约、布局值与缓存。

4 分钟阅读

审美是基础设施

当智能体生成越来越多最终交付的产出时,质量上限取决于你将审美判断编码进系统的能力。审美在变得可查询时才能规模化。

1 分钟阅读