mcpField
S
swiftui-liquid-glass

swiftui-liquid-glass

github.com/flowritescode设计与 UI447318 次安装3 周前更新
代码仓库

关于 swiftui-liquid-glass

swiftui-liquid-glass 是用于在 SwiftUI 中审查和实现原生 Liquid Glass 界面的技能,涵盖 API 选择、布局模式、可用性检查及常见视觉问题,面向 iOS 26 及更高版本。

主要功能

  1. 01选择原生玻璃按钮样式
  2. 02为自定义视图应用玻璃效果
  3. 03组合相邻的玻璃元素
  4. 04使用 safeAreaBar 放置底栏
  5. 05检查工具栏和符号规范
  6. 06为旧版 iOS 提供回退方案

适用场景

  1. 01重构自定义模糊玻璃效果
  2. 02构建玻璃按钮和自定义表面
  3. 03检查滚动布局中的玻璃效果

安装

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

$npx skills add https://github.com/flowritescode/fwc-swiftui-skills --skill swiftui-liquid-glass

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

附带文件reference.md

详细介绍

SwiftUI Liquid Glass

在 iOS 26 及更高版本上使用原生 Liquid Glass API。不要用材质、模糊或阴影重新制作这种效果。

核心规则

  1. 不要通过添加背景、描边、模糊和阴影来制作自定义 Liquid Glass。
  2. 按钮 — 样式:非彩色按钮使用 .buttonStyle(.glass),着色按钮使用 .buttonStyle(.glassProminent)。.glassProminent 支持 .tint(),但只能使用颜色(不能使用渐变)。
  3. 按钮 — 形状:使用 .buttonBorderShape(),不要手动为按钮标签应用形状。
  4. 按钮 — 内边距:这种按钮设置会在 Liquid Glass 形状内部增加约 13pt 的内边距;调整设计时请考虑这一点。
  5. 自定义视图:使用 .glassEffect(.regular, in: ...) 将自定义视图嵌入 Liquid Glass 容器。
  6. 组合玻璃效果:多个 Liquid Glass 元素相邻时,使用 GlassEffectContainer。当这些元素变大或彼此接触时,此视图 / 容器会产生液态融合效果。
  7. 滚动:避免在 ScrollView 和 List(任何可滚动内容)中使用 Liquid Glass。
  8. 底部栏:将 Liquid Glass 视图锚定到屏幕底部时,优先将其嵌入 .safeAreaBar(.bottom),而不是使用 VStack 或 .overlay()。safeAreaBar 会在其内容后方添加微妙的模糊效果。
  9. 工具栏项目 — 不显示玻璃效果:在 iOS 26 及更高版本上,导航栏和窗口工具栏项目默认会共享 Liquid Glass 背景。对于不应显示玻璃胶囊的项目(普通图标、自定义标签、状态文本、徽标),请在 ToolbarItem 上应用 .sharedBackgroundVisibility(.hidden),而不是应用在内部视图上。
  10. SF Symbols — 不使用预先包围的符号:不要在 Liquid Glass 按钮或容器中使用预先包围的 SF Symbol 变体(例如 plus.circle、xmark.circle.fill 或 trash.circle)。玻璃形状本身已充当容器;预先包围的符号会造成别扭的“双层包围”(圆形内又有一个圆形)。请使用基础 / 未包围的符号(plus、xmark、trash),并让 .buttonBorderShape() 或玻璃容器定义包围形状。

决策树

Need a button?
├─ Neutral / secondary → .buttonStyle(.glass)
└─ Tinted / primary    → .buttonStyle(.glassProminent).tint(someColor)

Icon in a glass button / surface?
└─ Plain unenclosed symbol (e.g. "plus", not "plus.circle") — glass provides enclosure

Need a custom non-button surface (chip, badge, card)?
└─ .glassEffect(.regular, in: shape) on the view content

Multiple glass elements nearby?
└─ Wrap in GlassEffectContainer(spacing: ...) { ... }

Fixed bottom toolbar / action bar?
└─ .safeAreaBar(.bottom) { ... }  — not VStack + overlay

Toolbar item without glass background?
└─ ToolbarItem { ... }.sharedBackgroundVisibility(.hidden)

Inside ScrollView, List, or Form rows?
└─ Do not use Liquid Glass — use solid/material fallback

工作流

1) 检查现有 UI
  • 标记伪装成玻璃效果的自定义模糊 / 材质堆叠。
  • 检查按钮是否使用 .glass / .glassProminent,而不是手动构建胶囊形状。
  • 确认使用 .buttonBorderShape(),而不是裁剪标签。
  • 确认组合元素位于 GlassEffectContainer 中。
  • 标记可滚动容器中的玻璃效果。
  • 检查锚定在底部的栏是否使用 .safeAreaBar(.bottom)。
  • 检查应以无玻璃效果方式显示的工具栏项目是否在 ToolbarItem 上使用 .sharedBackgroundVisibility(.hidden)。
  • 标记玻璃按钮或表面中的预先包围的 SF Symbols(例如 circle / square 变体)。
  • 使用 #available(iOS 26, *) 设置版本检查并提供回退方案。
2) 实现或重构
  1. 选择合适的原语(按钮样式、glassEffect 或 safeAreaBar)。
  2. 先应用布局和排版;最后添加玻璃效果修饰符。
  3. 将相邻的玻璃效果元素包装在 GlassEffectContainer 中。
  4. 匹配设计时,考虑约 13pt 的按钮内部内边距。
  5. 使用未包围的 SF Symbols,让玻璃形状提供包围几何形状。
  6. 添加 iOS 26 可用性检查和 iOS 26 之前版本的回退方案。

模式

玻璃按钮
// Secondary / neutral
Button("Cancel") { dismiss() }
    .buttonStyle(.glass)
    .buttonBorderShape(.capsule)

// Primary / tinted — color only, not gradient
Button("Save") { save() }
    .buttonStyle(.glassProminent)
    .tint(.blue)
    .buttonBorderShape(.roundedRectangle(radius: 12))

不要自行裁剪标签:

// ❌ Wrong — shape on label, not the glass button
Button { action() } label: {
    Text("Save")
        .padding()
        .background(.ultraThinMaterial, in: Capsule())
}

// ✅ Right — native glass handles shape and padding
Button("Save") { action() }
    .buttonStyle(.glassProminent)
    .buttonBorderShape(.capsule)

不要在玻璃按钮中使用预先包围的 SF Symbols:

// ❌ Wrong — pre-enclosed symbol creates redundant double enclosure
Button { add() } label: {
    Image(systemName: "plus.circle.fill")
}
.buttonStyle(.glass)
.buttonBorderShape(.circle)

// ✅ Right — plain symbol, glass shape provides the enclosure
Button { add() } label: {
    Image(systemName: "plus")
}
.buttonStyle(.glass)
.buttonBorderShape(.circle)
自定义玻璃表面
Label("3 items", systemImage: "tray")
    .padding(.horizontal, 16)
    .padding(.vertical, 10)
    .glassEffect(.regular, in: .capsule)

当表面会响应触摸时,添加 .interactive():

Text("Tap me")
    .padding()
    .glassEffect(.regular.interactive(), in: .rect(cornerRadius: 16))
组合玻璃效果(融合效果)
GlassEffectContainer(spacing: 24) {
    HStack(spacing: 24) {
        ToolButton(icon: "pencil")
        ToolButton(icon: "eraser")
        ToolButton(icon: "lasso")
    }
}

private struct ToolButton: View {
    let icon: String
    var body: some View {
        Image(systemName: icon)
            .frame(width: 56, height: 56)
            .font(.title2)
            .glassEffect(.regular, in: .circle)
    }
}

调整 spacing,控制元素之间的距离要多近才会触发液态融合效果。

底部操作栏
ContentView()
    .safeAreaBar(.bottom) {
        HStack {
            Button("Share") { share() }
                .buttonStyle(.glass)
            Button("Done") { done() }
                .buttonStyle(.glassProminent)
        }
    }

优先使用此方式,而不是通过 VStack { Spacer(); ... } 或 .overlay(alignment: .bottom) 固定位置。

不带玻璃效果的工具栏项

在 iOS 26 及更高版本中,同一逻辑分组中的工具栏项会共享 Liquid Glass 背景。当某个项应呈现裸露样式时,请将其隐藏:

.toolbar {
    ToolbarItem(placement: .principal) {
        Text("Draft")
            .font(.headline)
    }
    .sharedBackgroundVisibility(.hidden)

    ToolbarItem(placement: .topBarTrailing) {
        Button { add() } label: {
            Image(systemName: "plus")
        }
    }
    .sharedBackgroundVisibility(.hidden)

    ToolbarItem(placement: .topBarTrailing) {
        Button("Save") { save() }
            .buttonStyle(.glassProminent)
    }
}

在 ToolbarItem 上应用 .sharedBackgroundVisibility(.hidden),不要将其应用于内部的 Button 或标签。隐藏该效果会让此项单独分组,因此可能改变它与带玻璃效果的相邻项之间的间距。

不要将此修饰符应用于内部视图:

// ❌ Wrong — modifier on Button, glass background remains
ToolbarItem(placement: .topBarTrailing) {
    Button { add() } label: {
        Image(systemName: "plus")
    }
    .sharedBackgroundVisibility(.hidden)
}

// ✅ Right — modifier on ToolbarItem
ToolbarItem(placement: .topBarTrailing) {
    Button { add() } label: {
        Image(systemName: "plus")
    }
}
.sharedBackgroundVisibility(.hidden)
可用性回退
if #available(iOS 26, *) {
    content.glassEffect(.regular, in: .rect(cornerRadius: 16))
} else {
    content.background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 16))
}

反模式

反模式失败原因应改用
.background(.ultraThinMaterial) + 模糊 + 描边 + 阴影不是 Liquid Glass;光学效果不正确,也不会合并或变形.glassEffect(...) 或按钮样式
在 .glassProminent 上使用渐变 .tint()API 只接受颜色使用纯色 Color 色调,或使用不带 .glassProminent 色调的自定义标签
在 List/ScrollView 行上使用玻璃效果滚动 + 玻璃效果 = 视觉故障和性能开销使用不透明或材质行;玻璃效果仅用于固定界面元素
将形状应用于按钮标签缺少原生内边距(约 13pt),且边框渲染不正确.buttonBorderShape()
通过 .overlay 创建底部栏不会采用系统的模糊栏样式.safeAreaBar(.bottom)
在没有容器的情况下使用多个玻璃视图不会产生合并效果,渲染效果更差GlassEffectContainer
在本应不带玻璃效果的工具栏项上使用玻璃胶囊iOS 26 默认会为工具栏分组添加共享玻璃效果在 ToolbarItem 上使用 .sharedBackgroundVisibility(.hidden)
在内部视图上使用 .sharedBackgroundVisibility不会移除工具栏玻璃背景应用于 ToolbarItem(或其他 ToolbarContent)
在玻璃按钮中使用预先带圆形边框的 SF Symbols(plus.circle、xmark.circle.fill)重复的双重包围(“圆中有圆”);与玻璃形状冲突使用不带包围形状的符号(plus、xmark),让 .buttonBorderShape 提供容器

检查清单

  • 没有手工制作的模糊或材质玻璃仿制效果
  • 按钮使用 .glass 或 .glassProminent,并搭配 .buttonBorderShape()
  • 设计间距考虑了约 13pt 的按钮内部内边距
  • 自定义表面使用 .glassEffect(.regular, in: ...)
  • 使用 GlassEffectContainer 包裹相邻的玻璃效果
  • 滚动视图内没有玻璃效果
  • 底部界面元素使用 .safeAreaBar(.bottom)
  • 不带玻璃效果的工具栏项在 ToolbarItem 上使用 .sharedBackgroundVisibility(.hidden)
  • 玻璃按钮中没有预先带包围形状的 SF Symbols(例如,使用 "plus" 而非 "plus.circle")
  • 使用 #available(iOS 26, *),并为较旧的 OS 提供回退方案

其他资源

评论

支持 Markdown