liquid-glass-design
affaan-m/ECC
在 SwiftUI、UIKit 和 WidgetKit 中实现适用于 iOS 26 及以上版本的 Apple Liquid Glass 设计系统,包括动态玻璃材质、模糊效果、反射效果以及交互式变形效果。
...展开全部Liquid Glass 设计系统(iOS 26)
用于实现苹果“液态玻璃”效果的模式——这是一种动态材质,能够模糊其后方的内容,反射周围内容的色彩和光线,并响应触摸和指针交互。涵盖 SwiftUI、UIKit 和 WidgetKit 的集成。
何时启用
- 使用新设计语言构建或更新 iOS 26 及以上版本的应用程序时
- 实现玻璃风格的按钮、卡片、工具栏或容器
- 在玻璃元素之间创建形态变换过渡效果
- 将“液态玻璃”效果应用于小部件
- 将现有的模糊/Material 效果迁移到新的 Liquid Glass API
核心模式 — SwiftUI
基础玻璃效果
向任何视图添加“液态玻璃”效果的最简单方法:
Text("Hello, World!")
.font(.title)
.padding()
.glassEffect() // 默认:常规样式,胶囊形状
自定义形状和色调
Text("Hello, World!")
.font(.title)
.padding()
.glassEffect(.regular.tint(.orange).interactive(), in: .rect(cornerRadius: 16.0))
主要自定义选项:
.regular— 标准玻璃效果.tint(Color)— 添加色彩滤镜以增强醒目度.interactive()— 响应触摸和指针交互- 形状:
.capsule(默认)、.rect(cornerRadius:)、.circle
玻璃按钮样式
Button("点击我") { /* 操作 */ }
.buttonStyle(.glass)
Button("重要") { /* 操作 */ }
.buttonStyle(.glassProminent)
用于多个元素的 GlassEffectContainer
出于性能和形态变化考虑,请始终将多个玻璃视图包裹在容器中:
GlassEffectContainer(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()
}
}
间距参数控制合并距离——距离越近的元素,其玻璃形状融合得越紧密。
合并玻璃效果
使用glassEffectUnion 将多个视图合并为单一玻璃形状:
@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)
}
}
}
形态过渡
在玻璃元素出现/消失时创建平滑的变形效果:
@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的内容延伸至容器的左侧/右侧边缘。当布局延伸至边缘时,系统会自动处理侧边栏下方的滚动行为——无需额外修饰符。
核心模式 — UIKit
基础 UIGlassEffect
let 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)
])
// 向 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)
])
适用于多个元素的 UIGlassContainerEffect
let 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)
滚动边缘效果
scrollView.topEdgeEffect.style = .automatic
scrollView.bottomEdgeEffect.style = .hard
scrollView.leftEdgeEffect.isHidden = true
工具栏玻璃效果集成
let favoriteButton = UIBarButtonItem(image: UIImage(systemName: "heart"), style: .plain, target: self, action: #selector(favoriteAction))
favoriteButton.hidesSharedBackground = true // 禁用共享玻璃背景
核心模式 — WidgetKit
渲染模式检测
struct MyWidgetView: View {
@Environment(\.widgetRenderingMode) var renderingMode
var body: some View {
if renderingMode == .accented {
// 着色模式:白色着色、主题化玻璃背景
} else {
// 全彩模式:标准外观
}
}
}
用于视觉层次结构的强调组
HStack {
VStack(alignment: .leading) {
Text("标题")
.widgetAccentable() // 强调组
Text("副标题")
// 主组(默认)
}
Image(systemName: "star.fill")
.widgetAccentable() // 强调组
}
强调模式下的图像渲染
Image("myImage")
.widgetAccentedRenderingMode(.monochrome)
容器背景
VStack { /* 内容 */ }
.containerBackground(for: .widget) {
Color.blue.opacity(0.2)
}
关键设计决策
| 决策 | 理由 |
|---|---|
| GlassEffectContainer 包裹 | 性能优化,支持玻璃元素之间的形态转换 |
间距参数 |
控制合并距离——微调元素必须有多接近才能融合 |
@Namespace+glassEffectID |
在视图层次结构发生变化时启用平滑的形态转换 |
interactive()修饰符 |
显式启用触摸/指针交互响应——并非所有玻璃效果都应做出响应 |
| UIKit 中的 UIGlassContainerEffect | 为保持一致性,采用与 SwiftUI 相同的容器模式 |
| 小部件中的带强调效果的渲染模式 | 当用户选择带色调的主屏幕时,系统会应用带色调的玻璃效果 |
最佳实践
- 在为多个同级视图应用玻璃效果时,请始终使用 GlassEffectContainer—— 它支持形态变化并能提升渲染性能
- 在应用其他外观修饰符(如边框、字体、内边距)之后再应用
.glassEffect() - 仅对响应用户交互的元素(按钮、可切换项)使用
.interactive() - 请谨慎设置容器内的间距,以控制玻璃效果何时融合
- 在更改视图层次结构时使用
withAnimation,以实现平滑的形态转换 - 在各种外观模式下进行测试——浅色模式、深色模式以及强调色/着色模式
- 确保无障碍对比度——玻璃上的文本必须保持可读性
应避免的反模式
- 在未使用 GlassEffectContainer 的情况下,使用多个独立的
.glassEffect()视图 - 嵌套过多的玻璃效果——会降低性能并影响视觉清晰度
- 对每个视图都应用玻璃效果——应仅用于交互式元素、工具栏和卡片
- 在使用圆角时,忘记在 UIKit 中设置
clipsToBounds = true - 在小部件中忽略带重音的渲染模式——会导致主屏幕的着色外观失效
- 在玻璃效果背后使用不透明背景——会破坏半透明效果
何时使用
- 采用全新 iOS 26 设计的导航栏、工具栏和标签栏
- 悬浮操作按钮和卡片式容器
- 需要视觉深度和触觉反馈的交互式控件
- 应与系统“液态玻璃”外观相融合的小部件
- 相关 UI 状态之间的形态转换
---
name: liquid-glass-design
description: Implement Apple's Liquid Glass design system for iOS 26+ with dynamic glass materials, blur, reflection, and interactive morphing in SwiftUI, UIKit, and WidgetKit.
---
# Liquid Glass Design System (iOS 26)
Patterns for implementing Apple's Liquid Glass — a dynamic material that blurs content behind it, reflects color and light from surrounding content, and reacts to touch and pointer interactions. Covers SwiftUI, UIKit, and WidgetKit integration.
## When to Activate
- Building or updating apps for iOS 26+ with the new design language
- Implementing glass-style buttons, cards, toolbars, or containers
- Creating morphing transitions between glass elements
- Applying Liquid Glass effects to widgets
- Migrating existing blur/material effects to the new Liquid Glass API
## Core Pattern — SwiftUI
### Basic Glass Effect
The simplest way to add Liquid Glass to any view:
```swift
Text("Hello, World!")
.font(.title)
.padding()
.glassEffect() // Default: regular variant, capsule shape
```
### Customizing Shape and Tint
```swift
Text("Hello, World!")
.font(.title)
.padding()
.glassEffect(.regular.tint(.orange).interactive(), in: .rect(cornerRadius: 16.0))
```
Key customization options:
- `.regular` — standard glass effect
- `.tint(Color)` — add color tint for prominence
- `.interactive()` — react to touch and pointer interactions
- Shape: `.capsule` (default), `.rect(cornerRadius:)`, `.circle`
### Glass Button Styles
```swift
Button("Click Me") { /* action */ }
.buttonStyle(.glass)
Button("Important") { /* action */ }
.buttonStyle(.glassProminent)
```
### GlassEffectContainer for Multiple Elements
Always wrap multiple glass views in a container for performance and morphing:
```swift
GlassEffectContainer(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()
}
}
```
The `spacing` parameter controls merge distance — closer elements blend their glass shapes together.
### Uniting Glass Effects
Combine multiple views into a single glass shape with `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)
}
}
}
```
### Morphing Transitions
Create smooth morphing when glass elements appear/disappear:
```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)
```
### Extending Horizontal Scrolling Under Sidebar
To allow horizontal scroll content to extend under a sidebar or inspector, ensure the `ScrollView` content reaches the leading/trailing edges of the container. The system automatically handles the under-sidebar scrolling behavior when the layout extends to the edges — no additional modifier is needed.
## Core Pattern — UIKit
### Basic UIGlassEffect
```swift
let 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)
])
```
### UIGlassContainerEffect for Multiple Elements
```swift
let 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)
```
### Scroll Edge Effects
```swift
scrollView.topEdgeEffect.style = .automatic
scrollView.bottomEdgeEffect.style = .hard
scrollView.leftEdgeEffect.isHidden = true
```
### Toolbar Glass Integration
```swift
let favoriteButton = UIBarButtonItem(image: UIImage(systemName: "heart"), style: .plain, target: self, action: #selector(favoriteAction))
favoriteButton.hidesSharedBackground = true // Opt out of shared glass background
```
## Core Pattern — WidgetKit
### Rendering Mode Detection
```swift
struct 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
}
}
}
```
### Accent Groups for Visual Hierarchy
```swift
HStack {
VStack(alignment: .leading) {
Text("Title")
.widgetAccentable() // Accent group
Text("Subtitle")
// Primary group (default)
}
Image(systemName: "star.fill")
.widgetAccentable() // Accent group
}
```
### Image Rendering in Accented Mode
```swift
Image("myImage")
.widgetAccentedRenderingMode(.monochrome)
```
### Container Background
```swift
VStack { /* content */ }
.containerBackground(for: .widget) {
Color.blue.opacity(0.2)
}
```
## Key Design Decisions
| Decision | Rationale |
|----------|-----------|
| GlassEffectContainer wrapping | Performance optimization, enables morphing between glass elements |
| `spacing` parameter | Controls merge distance — fine-tune how close elements must be to blend |
| `@Namespace` + `glassEffectID` | Enables smooth morphing transitions on view hierarchy changes |
| `interactive()` modifier | Explicit opt-in for touch/pointer reactions — not all glass should respond |
| UIGlassContainerEffect in UIKit | Same container pattern as SwiftUI for consistency |
| Accented rendering mode in widgets | System applies tinted glass when user selects tinted Home Screen |
## Best Practices
- **Always use GlassEffectContainer** when applying glass to multiple sibling views — it enables morphing and improves rendering performance
- **Apply `.glassEffect()` after** other appearance modifiers (frame, font, padding)
- **Use `.interactive()`** only on elements that respond to user interaction (buttons, toggleable items)
- **Choose spacing carefully** in containers to control when glass effects merge
- **Use `withAnimation`** when changing view hierarchies to enable smooth morphing transitions
- **Test across appearances** — light mode, dark mode, and accented/tinted modes
- **Ensure accessibility contrast** — text on glass must remain readable
## Anti-Patterns to Avoid
- Using multiple standalone `.glassEffect()` views without a GlassEffectContainer
- Nesting too many glass effects — degrades performance and visual clarity
- Applying glass to every view — reserve for interactive elements, toolbars, and cards
- Forgetting `clipsToBounds = true` in UIKit when using corner radii
- Ignoring accented rendering mode in widgets — breaks tinted Home Screen appearance
- Using opaque backgrounds behind glass — defeats the translucency effect
## When to Use
- Navigation bars, toolbars, and tab bars with the new iOS 26 design
- Floating action buttons and card-style containers
- Interactive controls that need visual depth and touch feedback
- Widgets that should integrate with the system's Liquid Glass appearance
- Morphing transitions between related UI states
所有文件
1 个文件安装 liquid-glass-design
下载技能文件并将其解压到 .claude/skills/ 目录中。
下载ZIP克隆仓库并复制技能文件到您的项目中。
git clone https://github.com/affaan-m/ECC/tree/main/skills/liquid-glass-design # Copy SKILL.md to your .claude/skills/ directory
复制





首页
