mcpField
S
swiftui-liquid-glass

swiftui-liquid-glass

github.com/dpearson2699设计与 UI1.2k4.2k 次安装13 周前更新
代码仓库

关于 swiftui-liquid-glass

面向 SwiftUI 开发者的技能指南,介绍如何在 iOS 26 及更高版本中实现和审查 Liquid Glass。重点涵盖控件与导航表面的使用、动效、可访问性和旧版本回退。

主要功能

  1. 01Liquid Glass API 用法
  2. 02玻璃效果容器与融合
  3. 03形变标识和过渡
  4. 04玻璃按钮样式
  5. 05可访问性与版本回退检查

适用场景

  1. 01为浮动控件添加玻璃效果
  2. 02改造现有导航和控件背景
  3. 03审查动效与交互实现
  4. 04检查旧版系统和辅助功能回退

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/dpearson2699/swift-ios-skills --skill swiftui-liquid-glass

安装后在 Claude Code 中输入/swiftui-liquid-glass确认已加载。

附带文件evals/evals.jsonreferences/liquid-glass.md

详细介绍

SwiftUI Liquid Glass

Liquid Glass 是 Apple 各平台引入的动态半透明材质。使用当前 SDK 构建时,标准 SwiftUI 栏和演示会自动采用它。自定义玻璃效果应仅用于功能控件和导航表面,而非一般内容背景。

完整的 API 参考和更多示例,请参阅 references/liquid-glass.md。

目录

工作流

根据请求选择相应的流程:

1. 使用 Liquid Glass 实现新功能
  1. 确定目标表面(悬浮控件、自定义栏、临时控件)。
  2. 决定形状、强调程度,以及各元素是真正的控件还是静态状态。
  3. 将成组的玻璃元素放入 GlassEffectContainer。
  4. 在布局和外观修饰符之后应用 .glassEffect()。
  5. 仅对可轻点或可聚焦的元素添加 .interactive()。
  6. 在视图层级随动画变化时,使用 glassEffectID(_:in:) 添加形变过渡。将 glassEffectTransition(_:) 放在插入或移除的玻璃子视图上,而不是始终存在的容器上,并根据形变与过渡选择样式。
  7. 使用 if #available(iOS 26, *) 控制可用性,并为较早版本提供回退方案。
2. 使用 Liquid Glass 改进现有功能
  1. 找出可替换为 .glassEffect() 的自定义控件或导航背景。
  2. 将同级玻璃元素放入 GlassEffectContainer,以实现融合并提升性能。
  3. 将类似玻璃效果的自定义按钮替换为 .buttonStyle(.glass)、.buttonStyle(.glassProminent) 或 .buttonStyle(.glass(.clear)) 等可配置样式。按钮需要特定色调或变体时,使用 .glass(_:);.glassProminent 仅用于强调度较高的主要操作。
  4. 在发生动画插入或移除的地方添加形变过渡。
3. 检查现有的 Liquid Glass 用法

逐项检查每个效果的内容与控件归属、布局顺序、容器范围、交互性、过渡效果、可用性、辅助功能设置和回退方案。每次修正后,恢复相同的 UI 测试场景并重新运行检查清单。

核心 API 摘要

glassEffect(_:in:)

在视图后应用 Liquid Glass。默认值:Capsule 形状的 .regular 变体。

nonisolated func glassEffect(
    _ glass: Glass = .regular,
    in shape: some Shape = DefaultGlassEffectShape()
) -> some View
Glass 结构体
属性 / 方法用途
.regular标准玻璃材质
.clear透明变体;可读性需要时,添加调暗或对比度处理
.identity无视觉效果(直接传递)
.tint(_:)添加颜色色调以增强强调效果
.interactive(_:)响应触控和指针交互

可将它们串联使用:.regular.tint(.blue).interactive()

GlassEffectContainer

将多个玻璃视图包裹起来,以共享渲染、融合和形变效果。

GlassEffectContainer(spacing: 24) {
    // child views with .glassEffect()
}

spacing 控制相邻玻璃形状开始融合的距离。将其设置为与内部布局间距相同或更大,使形状在动画过渡期间融合,而在静止时保持分离。

形变与过渡
修饰符用途
glassEffectID(_:in:)视图层级变化期间用于形变的稳定标识
glassEffectUnion(id:namespace:)将多个视图合并为一个玻璃形状
glassEffectTransition(_:)控制玻璃的出现或消失方式

过渡选择:对于容器间距范围内的相邻效果,使用 .matchedGeometry;对于远距离插入或移除,或不应进行几何匹配的情况,使用 .materialize;只有在不需要过渡动画时才使用 .identity。

按钮样式
Button("Action") { }
    .buttonStyle(.glass)           // standard glass button

Button("Primary") { }
    .buttonStyle(.glassProminent)  // prominent glass button

Button("Media") { }
    .buttonStyle(.glass(.clear))    // configurable variant; verify contrast
相关的 iOS 26 API
API用途
scrollEdgeEffectStyle配置滚动边界的视觉效果。
backgroundExtensionEffect将同一背景延伸至安全区域边缘,并添加镜像模糊效果。
ToolbarSpacer在工具栏项目之间创建视觉间隔。

签名和示例请参阅 references/liquid-glass.md 中的相应章节。

代码示例

带可用性检查的玻璃按钮
if #available(iOS 26, *) {
    Button("Show Status") { showStatusDetails() }
        .buttonStyle(.glass)
} else {
    Button("Show Status") { showStatusDetails() }
        .buttonStyle(.bordered)
}
容器中成组的玻璃形状
let symbols = ["pencil", "eraser.fill", "lasso"]

GlassEffectContainer(spacing: 24) {
    HStack(spacing: 24) {
        ForEach(symbols, id: \.self) { symbol in
            Image(systemName: symbol)
                .frame(width: 56, height: 56)
                .glassEffect()
        }
    }
}
邻近视图的形变过渡
@State private var isExpanded = false
@Namespace private var ns

var body: some View {
    GlassEffectContainer(spacing: 40) {
        HStack(spacing: 40) {
            Image(systemName: "pencil")
                .frame(width: 80, height: 80)
                .glassEffect()
                .glassEffectID("pencil", in: ns)

            if isExpanded {
                Image(systemName: "eraser.fill")
                    .frame(width: 80, height: 80)
                    .glassEffect()
                    .glassEffectID("eraser", in: ns)
                    .glassEffectTransition(.matchedGeometry)
            }
        }
    }

    Button("Toggle") {
        withAnimation { isExpanded.toggle() }
    }
    .buttonStyle(.glass)
}
将多个视图合并为单个玻璃形状
@Namespace private var ns

GlassEffectContainer(spacing: 20) {
    HStack(spacing: 20) {
        ForEach(items.indices, id: \.self) { i in
            Image(systemName: items[i])
                .frame(width: 80, height: 80)
                .glassEffect()
                .glassEffectUnion(id: i < 2 ? "group1" : "group2", namespace: ns)
        }
    }
}
带色调的玻璃图标控件
struct GlassIconControl: View {
    let icon: String
    let tint: Color
    let action: () -> Void

    var body: some View {
        Button(action: action) {
            Image(systemName: icon)
                .font(.title2)
                .padding()
        }
        .buttonStyle(.glass(.regular.tint(tint)))
    }
}
明亮内容上的透明玻璃操作
if #available(iOS 26, *) {
    ZStack {
        Capsule()
            .fill(.black.opacity(0.28))

        Button {
            playRecap()
        } label: {
            Label("Play", systemImage: "play.fill")
                .font(.headline)
                .padding(.horizontal, 8)
        }
        .buttonStyle(.glass(.clear))
    }
    .fixedSize()
} else {
    Button("Play", systemImage: "play.fill") { playRecap() }
        .buttonStyle(.borderedProminent)
}

仅当背景仍能让标签和符号清晰可读时,才使用透明玻璃。 对于明亮或繁杂的背景,请添加微妙的变暗图层,或选择不那么透明的 按钮样式。

静态状态计数,而非工具栏控件
VStack(spacing: 8) {
    Text("24")
        .font(.headline.monospacedDigit())
        .accessibilityLabel("24 options expiring")

    Text("Options Expiring")
        .font(.subheadline)
        .foregroundStyle(.secondary)
}
// Keep read-only status out of toolbar control slots and do not add .interactive().

常见错误

错误修正方法
玻璃效果装饰静态内容将其用于控件/导航层。
只读状态使用 .interactive() 或操作槽位将状态作为内容呈现,或让整个徽标成为一个真正可访问的操作。
相关效果使用嵌套容器每个相关的混合/形变组使用一个 GlassEffectContainer。
.glassEffect() 位于内边距/框架/样式之前先应用布局和外观,再添加玻璃效果。
自定义效果假设使用默认辅助功能设置测试“降低透明度”“降低动态效果”、对比度和易读性。
没有 iOS 26 之前的处理路径对效果进行可用性检查,并保留可用的回退方案。

审查清单

  • 可用性:包含 if #available(iOS 26, *),并提供回退 UI。
  • 容器:多个玻璃视图由 GlassEffectContainer 包裹。
  • 修饰符顺序:在布局/外观修饰符之后应用 .glassEffect()。
  • 交互性:仅在存在用户交互时使用 .interactive()。
  • 状态与操作:静态计数/状态不是工具栏控件,也不呈现按下/悬停提示。
  • 过渡:形变动画使用 @Namespace 和 glassEffectID。
  • 过渡类型:邻近效果使用 .matchedGeometry;远距离效果使用 .materialize,并应用于条件式玻璃子视图。
  • 一致性:相关元素的形状、色调和间距保持统一。
  • 性能:限制玻璃效果的数量;对效果分组时使用容器。
  • 辅助功能:启用“降低透明度”和“降低动态效果”后进行测试。
  • 按钮样式:按钮使用标准的 .glass、.glassProminent 或可配置的 .glass(_:);需要色调或透明变体时,优先使用 .glass(_:)。
  • 透明玻璃对比度:明亮内容上的透明玻璃需添加变暗/对比度处理,或改用更易读的样式。
  • 并发:传递给 glassEffectID/glassEffectUnion 的 ID 符合 Sendable;带 MainActor 注解的 Liquid Glass API 应留在 SwiftUI UI 代码中。

参考资料

评论

支持 Markdown