Install any skill in seconds. Free to start, no credit card required.
Get Started Free →日本語翻訳:このファイルは liquid-glass-design 用の日本語翻訳が必要です
.claude/skills/affaan-m-liquid-glass-design/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 62% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 10% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 51% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 90% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 52% | 0% |
实现苹果 Liquid Glass 的模式指南——这是一种动态材质,会模糊其后的内容,反射周围内容的颜色和光线,并对触摸和指针交互做出反应。涵盖 SwiftUI、UIKit 和 WidgetKit 集成。
为任何视图添加 Liquid Glass 的最简单方法:
swiftText("Hello, World!") .font(.title) .padding() .glassEffect() // Default: regular variant, capsule shape
swiftText("Hello, World!") .font(.title) .padding() .glassEffect(.regular.tint(.orange).interactive(), in: .rect(cornerRadius: 16.0))
关键自定义选项:
.regular — 标准玻璃效果.tint(Color) — 添加颜色色调以增强突出度.interactive() — 对触摸和指针交互做出反应.capsule(默认)、.rect(cornerRadius:)、.circleswiftButton("Click Me") { /* action */ } .buttonStyle(.glass) Button("Important") { /* action */ } .buttonStyle(.glassProminent)
出于性能和变形考虑,始终将多个玻璃视图包装在一个容器中:
swiftGlassEffectContainer(spacing: 40.0) { HStack(spacing: 40.0) { Image(systemName: "scribble.variable") .frame(width: 80.0, height: 80.0) .font(.system(size: 36)) .glassEffect() Image(systemName: "eraser.fill") .frame(width: 80.0, height: 80.0) .font(.system(size: 36)) .glassEffect() } }
spacing 参数控制合并距离——距离更近的元素会将其玻璃形状融合在一起。
使用 glassEffectUnion 将多个视图组合成单个玻璃形状:
swift@Namespace private var namespace GlassEffectContainer(spacing: 20.0) { HStack(spacing: 20.0) { ForEach(symbolSet.indices, id: \.self) { item in Image(systemName: symbolSet[item]) .frame(width: 80.0, height: 80.0) .glassEffect() .glassEffectUnion(id: item < 2 ? "group1" : "group2", namespace: namespace) } } }
在玻璃元素出现/消失时创建平滑的变形效果:
swift@State private var isExpanded = false @Namespace private var namespace GlassEffectContainer(spacing: 40.0) { HStack(spacing: 40.0) { Image(systemName: "scribble.variable") .frame(width: 80.0, height: 80.0) .glassEffect() .glassEffectID("pencil", in: namespace) if isExpanded { Image(systemName: "eraser.fill") .frame(width: 80.0, height: 80.0) .glassEffect() .glassEffectID("eraser", in: namespace) } } } Button("Toggle") { withAnimation { isExpanded.toggle() } } .buttonStyle(.glass)
要允许水平滚动内容延伸到侧边栏或检查器下方,请确保 ScrollView 内容到达容器的 leading/trailing 边缘。当布局延伸到边缘时,系统会自动处理侧边栏下方的滚动行为——无需额外的修饰符。
swiftlet glassEffect = UIGlassEffect() glassEffect.tintColor = UIColor.systemBlue.withAlphaComponent(0.3) glassEffect.isInteractive = true let visualEffectView = UIVisualEffectView(effect: glassEffect) visualEffectView.translatesAutoresizingMaskIntoConstraints = false visualEffectView.layer.cornerRadius = 20 visualEffectView.clipsToBounds = true view.addSubview(visualEffectView) NSLayoutConstraint.activate([ visualEffectView.centerXAnchor.constraint(equalTo: view.centerXAnchor), visualEffectView.centerYAnchor.constraint(equalTo: view.centerYAnchor), visualEffectView.widthAnchor.constraint(equalToConstant: 200), visualEffectView.heightAnchor.constraint(equalToConstant: 120) ]) // Add content to contentView let label = UILabel() label.text = "Liquid Glass" label.translatesAutoresizingMaskIntoConstraints = false visualEffectView.contentView.addSubview(label) NSLayoutConstraint.activate([ label.centerXAnchor.constraint(equalTo: visualEffectView.contentView.centerXAnchor), label.centerYAnchor.constraint(equalTo: visualEffectView.contentView.centerYAnchor) ])
swiftlet containerEffect = UIGlassContainerEffect() containerEffect.spacing = 40.0 let containerView = UIVisualEffectView(effect: containerEffect) let firstGlass = UIVisualEffectView(effect: UIGlassEffect()) let secondGlass = UIVisualEffectView(effect: UIGlassEffect()) containerView.contentView.addSubview(firstGlass) containerView.contentView.addSubview(secondGlass)
swiftscrollView.topEdgeEffect.style = .automatic scrollView.bottomEdgeEffect.style = .hard scrollView.leftEdgeEffect.isHidden = true
swiftlet favoriteButton = UIBarButtonItem(image: UIImage(systemName: "heart"), style: .plain, target: self, action: #selector(favoriteAction)) favoriteButton.hidesSharedBackground = true // Opt out of shared glass background
swiftstruct MyWidgetView: View { @Environment(\.widgetRenderingMode) var renderingMode var body: some View { if renderingMode == .accented { // Tinted mode: white-tinted, themed glass background } else { // Full color mode: standard appearance } } }
swiftHStack { VStack(alignment: .leading) { Text("Title") .widgetAccentable() // Accent group Text("Subtitle") // Primary group (default) } Image(systemName: "star.fill") .widgetAccentable() // Accent group }
swiftImage("myImage") .widgetAccentedRenderingMode(.monochrome)
swiftVStack { /* content */ } .containerBackground(for: .widget) { Color.blue.opacity(0.2) }
| 决策 | 理由 | |----------|-----------| | 使用 GlassEffectContainer 包装 | 性能优化,实现玻璃元素之间的变形 | | spacing 参数 | 控制合并距离——微调元素需要多近才能融合 | | @Namespace + glassEffectID | 在视图层次结构变化时实现平滑的变形过渡 | | interactive() 修饰符 | 明确选择加入触摸/指针反应——并非所有玻璃都应响应 | | UIKit 中的 UIGlassContainerEffect | 与 SwiftUI 保持一致的容器模式 | | 小组件中的强调色渲染模式 | 当用户选择带色调的主屏幕时,系统会应用带色调的玻璃效果 |
.glassEffect().interactive()withAnimation,以启用平滑的变形过渡.glassEffect() 视图而不使用 GlassEffectContainerclipsToBounds = true| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 16,603 | 13,384 | -19% | 1 | 1 | 0% | 3,283 | 5,314 | +62% | 0 | 0 | — |
case-02 | fail→pass | 21,780 | 13,466 | -38% | 1 | 1 | 0% | 4,900 | 5,366 | +10% | 0 | 0 | — |
case-03 | fail→pass | 14,617 | 8,866 | -39% | 1 | 1 | 0% | 2,646 | 3,988 | +51% | 0 | 0 | — |
case-04 | pass→pass | 10,115 | 4,995 | -51% | 1 | 1 | 0% | 1,707 | 3,237 | +90% | 0 | 0 | — |
case-05 | fail→pass | 8,164 | 2,964 | -64% | 1 | 1 | 0% | 1,450 | 2,755 | +90% | 0 | 0 | — |
case-06 | fail→pass | 16,815 | 12,771 | -24% | 1 | 1 | 0% | 3,409 | 5,190 | +52% | 0 | 0 | — |
case-07 | fail→pass | 14,871 | 4,788 | -68% | 1 | 1 | 0% | 2,493 | 3,263 | +31% | 0 | 0 | — |
case-08 | fail→pass | 21,083 | 5,276 | -75% | 1 | 1 | 0% | 4,280 | 3,271 | -24% | 0 | 0 | — |
case-09 | fail→pass | 13,575 | 4,110 | -70% | 1 | 1 | 0% | 2,794 | 3,099 | +11% | 0 | 0 | — |
case-10 | fail→pass | 14,375 | 3,204 | -78% | 1 | 1 | 0% | 2,478 | 2,810 | +13% | 0 | 0 | — |
case-11 | pass→pass | 6,771 | 5,828 | -14% | 1 | 1 | 0% | 1,190 | 3,237 | +172% | 0 | 0 | — |
case-12 | pass→pass | 10,695 | 7,424 | -31% | 1 | 1 | 0% | 2,292 | 3,719 | +62% | 0 | 0 | — |
case-13 | pass→pass | 9,521 | 6,969 | -27% | 1 | 1 | 0% | 1,936 | 3,737 | +93% | 0 | 0 | — |
case-14 | fail→pass | 10,865 | 9,952 | -8% | 1 | 1 | 0% | 1,992 | 4,023 | +102% | 0 | 0 | — |
case-15 | pass→pass | 10,762 | 7,252 | -33% | 1 | 1 | 0% | 1,778 | 3,475 | +95% | 0 | 0 | — |
case-16 | fail→pass | 8,020 | 3,871 | -52% | 1 | 1 | 0% | 1,388 | 2,914 | +110% | 0 | 0 | — |
case-17 | pass→pass | 6,439 | 2,954 | -54% | 1 | 1 | 0% | 1,238 | 2,835 | +129% | 0 | 0 | — |
case-18 | fail→pass | 6,889 | 1,819 | -74% | 1 | 1 | 0% | 1,178 | 2,573 | +118% | 0 | 0 | — |
case-19 | fail→pass | 10,605 | 6,689 | -37% | 1 | 1 | 0% | 1,914 | 3,366 | +76% | 0 | 0 | — |
case-20 | fail→pass | 17,341 | 3,146 | -82% | 1 | 1 | 0% | 2,961 | 2,784 | -6% | 0 | 0 | — |
case-21 | pass→pass | 7,519 | 3,682 | -51% | 1 | 1 | 0% | 1,240 | 2,837 | +129% | 0 | 0 | — |
case-22 | fail→pass | 3,952 | 3,613 | -9% | 1 | 1 | 0% | 780 | 2,987 | +283% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +68 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.