liquid-glass-design
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseLiquid Glass Design System (iOS 26)
Liquid Glass设计系统(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.
本文介绍了实现Apple Liquid Glass的相关模式——这是一种动态材质,可模糊其后方的内容,反射周围内容的色彩和光线,并对触摸和指针交互做出响应。内容涵盖SwiftUI、UIKit和WidgetKit的集成方法。
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
- 为iOS 26+版本的应用构建或更新新设计语言
- 实现玻璃风格的按钮、卡片、工具栏或容器
- 创建玻璃元素之间的变形过渡效果
- 为小组件应用Liquid Glass效果
- 将现有模糊/材质效果迁移至新的Liquid Glass API
Core Pattern — SwiftUI
核心实现模式 — 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为任意视图添加Liquid Glass的最简方式:
swift
Text("Hello, World!")
.font(.title)
.padding()
.glassEffect() // Default: regular variant, capsule shapeCustomizing Shape and Tint
自定义形状与色调
swift
Text("Hello, World!")
.font(.title)
.padding()
.glassEffect(.regular.tint(.orange).interactive(), in: .rect(cornerRadius: 16.0))Key customization options:
- — standard glass effect
.regular - — add color tint for prominence
.tint(Color) - — react to touch and pointer interactions
.interactive() - Shape: (default),
.capsule,.rect(cornerRadius:).circle
swift
Text("Hello, World!")
.font(.title)
.padding()
.glassEffect(.regular.tint(.orange).interactive(), in: .rect(cornerRadius: 16.0))关键自定义选项:
- — 标准玻璃效果
.regular - — 添加色彩色调以突出显示
.tint(Color) - — 响应触摸和指针交互
.interactive() - 形状:(默认)、
.capsule、.rect(cornerRadius:).circle
Glass Button Styles
玻璃按钮样式
swift
Button("Click Me") { /* action */ }
.buttonStyle(.glass)
Button("Important") { /* action */ }
.buttonStyle(.glassProminent)swift
Button("Click Me") { /* action */ }
.buttonStyle(.glass)
Button("Important") { /* action */ }
.buttonStyle(.glassProminent)GlassEffectContainer for Multiple Elements
多元素容器GlassEffectContainer
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 parameter controls merge distance — closer elements blend their glass shapes together.
spacing当为多个玻璃视图添加效果时,务必将其包裹在容器中,以提升性能并支持变形效果:
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()
}
}spacingUniting Glass Effects
玻璃效果合并
Combine multiple views into a single glass shape with :
glassEffectUnionswift
@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)
}
}
}使用将多个视图合并为单个玻璃形状:
glassEffectUnionswift
@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)当玻璃元素显示/隐藏时,创建流畅的变形动画:
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 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.
ScrollView若要让横向滚动内容延伸至侧边栏或检查器下方,需确保内容触及容器的首尾边缘。当布局延伸至边缘时,系统会自动处理侧边栏下的滚动行为——无需额外修饰符。
ScrollViewCore Pattern — UIKit
核心实现模式 — UIKit
Basic UIGlassEffect
基础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)
])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
多元素容器UIGlassContainerEffect
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)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 = trueswift
scrollView.topEdgeEffect.style = .automatic
scrollView.bottomEdgeEffect.style = .hard
scrollView.leftEdgeEffect.isHidden = trueToolbar 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 backgroundswift
let favoriteButton = UIBarButtonItem(image: UIImage(systemName: "heart"), style: .plain, target: self, action: #selector(favoriteAction))
favoriteButton.hidesSharedBackground = true // Opt out of shared glass backgroundCore Pattern — WidgetKit
核心实现模式 — 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
}
}
}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
}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)swift
Image("myImage")
.widgetAccentedRenderingMode(.monochrome)Container Background
容器背景
swift
VStack { /* content */ }
.containerBackground(for: .widget) {
Color.blue.opacity(0.2)
}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 |
| Controls merge distance — fine-tune how close elements must be to blend |
| Enables smooth morphing transitions on view hierarchy changes |
| 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 |
| 决策 | 理由 |
|---|---|
| 使用GlassEffectContainer包裹 | 优化性能,支持玻璃元素间的变形效果 |
| 控制融合距离——微调元素需要多近才能融合 |
| 当视图层级变化时,实现流畅的变形过渡 |
| 显式开启触摸/指针响应——并非所有玻璃元素都需要响应 |
| UIKit中使用UIGlassContainerEffect | 与SwiftUI采用相同的容器模式,保持一致性 |
| 小组件中的强调渲染模式 | 当用户选择色调化主屏幕时,系统会应用色调化玻璃效果 |
Best Practices
最佳实践
- Always use GlassEffectContainer when applying glass to multiple sibling views — it enables morphing and improves rendering performance
- Apply after other appearance modifiers (frame, font, padding)
.glassEffect() - Use only on elements that respond to user interaction (buttons, toggleable items)
.interactive() - Choose spacing carefully in containers to control when glass effects merge
- Use when changing view hierarchies to enable smooth morphing transitions
withAnimation - Test across appearances — light mode, dark mode, and accented/tinted modes
- Ensure accessibility contrast — text on glass must remain readable
- 始终使用GlassEffectContainer:当为多个同级视图添加玻璃效果时,它能实现变形效果并提升渲染性能
- 在其他外观修饰符之后应用:比如frame、font、padding等
.glassEffect() - 仅在可交互元素上使用:比如按钮、可切换项
.interactive() - 谨慎选择容器的spacing值:控制玻璃效果的融合时机
- 在修改视图层级时使用:实现流畅的变形过渡动画
withAnimation - 在不同外观模式下测试:浅色模式、深色模式以及强调/色调模式
- 确保可访问性对比度:玻璃上的文字必须保持可读
Anti-Patterns to Avoid
需避免的反模式
- Using multiple standalone views without a GlassEffectContainer
.glassEffect() - Nesting too many glass effects — degrades performance and visual clarity
- Applying glass to every view — reserve for interactive elements, toolbars, and cards
- Forgetting in UIKit when using corner radii
clipsToBounds = true - Ignoring accented rendering mode in widgets — breaks tinted Home Screen appearance
- Using opaque backgrounds behind glass — defeats the translucency effect
- 不使用GlassEffectContainer,直接使用多个独立的视图
.glassEffect() - 嵌套过多玻璃效果——会降低性能和视觉清晰度
- 为每个视图都添加玻璃效果——仅用于交互元素、工具栏和卡片
- UIKit中使用圆角半径时忘记设置
clipsToBounds = true - 忽略小组件的强调渲染模式——会破坏色调化主屏幕的显示效果
- 在玻璃后方使用不透明背景——会抵消半透明效果
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
- 采用iOS 26新设计的导航栏、工具栏和标签栏
- 浮动操作按钮和卡片式容器
- 需要视觉深度和触摸反馈的交互控件
- 需与系统Liquid Glass外观集成的小组件
- 相关UI状态间的变形过渡效果