liquid-glass-design

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Liquid 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 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
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
spacing
parameter controls merge distance — closer elements blend their glass shapes together.
当为多个玻璃视图添加效果时,务必将其包裹在容器中,以提升性能并支持变形效果:
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()
    }
}
spacing
参数控制融合距离——距离越近的元素,其玻璃形状越容易融合。

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)
        }
    }
}
使用
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)
当玻璃元素显示/隐藏时,创建流畅的变形动画:
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.
若要让横向滚动内容延伸至侧边栏或检查器下方,需确保
ScrollView
内容触及容器的首尾边缘。当布局延伸至边缘时,系统会自动处理侧边栏下的滚动行为——无需额外修饰符。

Core 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 = true
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
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

核心实现模式 — 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

关键设计决策

DecisionRationale
GlassEffectContainer wrappingPerformance 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 UIKitSame container pattern as SwiftUI for consistency
Accented rendering mode in widgetsSystem applies tinted glass when user selects tinted Home Screen
决策理由
使用GlassEffectContainer包裹优化性能,支持玻璃元素间的变形效果
spacing
参数
控制融合距离——微调元素需要多近才能融合
@Namespace
+
glassEffectID
当视图层级变化时,实现流畅的变形过渡
interactive()
修饰符
显式开启触摸/指针响应——并非所有玻璃元素都需要响应
UIKit中使用UIGlassContainerEffect与SwiftUI采用相同的容器模式,保持一致性
小组件中的强调渲染模式当用户选择色调化主屏幕时,系统会应用色调化玻璃效果

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
  • 始终使用GlassEffectContainer:当为多个同级视图添加玻璃效果时,它能实现变形效果并提升渲染性能
  • 在其他外观修饰符之后应用
    .glassEffect()
    :比如frame、font、padding等
  • 仅在可交互元素上使用
    .interactive()
    :比如按钮、可切换项
  • 谨慎选择容器的spacing值:控制玻璃效果的融合时机
  • 在修改视图层级时使用
    withAnimation
    :实现流畅的变形过渡动画
  • 在不同外观模式下测试:浅色模式、深色模式以及强调/色调模式
  • 确保可访问性对比度:玻璃上的文字必须保持可读

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
  • 不使用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状态间的变形过渡效果