Was macht Liquid Glass Design System (iOS 26)?
Patterns zur Implementierung von Apples Liquid Glass — einem dynamischen Material, das den dahinterliegenden Inhalt unscharf macht, Farbe und Licht der umgebenden Inhalte reflektiert und auf Berührungen und Pointer-Interaktionen reagiert. Deckt SwiftUI-, UIKit- und WidgetKit-Integration ab.
Wann aktivieren
- Entwickeln oder Aktualisieren von Apps für iOS 26+ mit der neuen Designsprache
- Implementieren von glasartigen Schaltflächen, Karten, Symbolleisten oder Containern
- Erstellen von Morphing-Übergängen zwischen Glaselementen
- Anwenden von Liquid Glass-Effekten auf Widgets
- Migrieren bestehender Unschärfe-/Materialeffekte zur neuen Liquid Glass API
Kernmuster — SwiftUI
Einfacher Glaseffekt
Der einfachste Weg, Liquid Glass zu einer Ansicht hinzuzufügen:
Text("Hello, World!")
.font(.title)
.padding()
.glassEffect() // Standard: reguläre Variante, Kapselform
Anpassen von Form und Farbton
Text("Hello, World!")
.font(.title)
.padding()
.glassEffect(.regular.tint(.orange).interactive(), in: .rect(cornerRadius: 16.0))
Wichtige Anpassungsoptionen:
.regular— Standard-Glaseffekt.tint(Color)— Farbe für Hervorhebung hinzufügen.interactive()— auf Berührungen und Pointer-Interaktionen reagieren- Form:
.capsule(Standard),.rect(cornerRadius:),.circle
Glasschaltflächen-Stile
Button("Click Me") { /* Aktion */ }
.buttonStyle(.glass)
Button("Wichtig") { /* Aktion */ }
.buttonStyle(.glassProminent)
GlassEffectContainer für mehrere Elemente
Mehrere Glasansichten immer in einen Container einwickeln, für Leistung und Morphing:
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()
}
}
Der Parameter spacing steuert den Merge-Abstand — nähere Elemente verschmelzen ihre Glasformen.
Glaseffekte vereinen
Mehrere Ansichten mit glassEffectUnion zu einer einzigen Glasform kombinieren:
@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-Übergänge
Sanftes Morphing erstellen, wenn Glaselemente erscheinen/verschwinden:
@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)
Horizontales Scrollen unter der Seitenleiste verlängern
Damit horizontaler Scroll-Inhalt unter einer Seitenleiste oder einem Inspektor verlaufen kann, muss der ScrollView-Inhalt die linken/rechten Ränder des Containers erreichen. Das System übernimmt automatisch das Scrollverhalten unter der Seitenleiste, wenn das Layout bis zu den Rändern reicht — kein zusätzlicher Modifikator erforderlich.
Kernmuster — UIKit
Einfacher 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)
])
// Inhalt zur contentView hinzufügen
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 für mehrere Elemente
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)
Randeffekte beim Scrollen
scrollView.topEdgeEffect.style = .automatic
scrollView.bottomEdgeEffect.style = .hard
scrollView.leftEdgeEffect.isHidden = true
Toolbar-Glasintegration
let favoriteButton = UIBarButtonItem(image: UIImage(systemName: "heart"), style: .plain, target: self, action: #selector(favoriteAction))
favoriteButton.hidesSharedBackground = true // Auf gemeinsamen Glashintergrund verzichten
Kernmuster — WidgetKit
Erkennung des Rendering-Modus
struct MyWidgetView: View {
@Environment(\.widgetRenderingMode) var renderingMode
var body: some View {
if renderingMode == .accented {
// Getönter Modus: weiß getönter, thematischer Glashintergrund
} else {
// Vollfarbmodus: Standarddarstellung
}
}
}
Akzentgruppen für visuelle Hierarchie
HStack {
VStack(alignment: .leading) {
Text("Titel")
.widgetAccentable() // Akzentgruppe
Text("Untertitel")
// Primäre Gruppe (Standard)
}
Image(systemName: "star.fill")
.widgetAccentable() // Akzentgruppe
}
Bilddarstellung im akzentuierten Modus
Image("myImage")
.widgetAccentedRenderingMode(.monochrome)
Containerhintergrund
VStack { /* Inhalt */ }
.containerBackground(for: .widget) {
Color.blue.opacity(0.2)
}
Wichtige Designentscheidungen
| Entscheidung | Begründung |
|---|---|
| GlassEffectContainer-Umhüllung | Leistungsoptimierung, ermöglicht Morphing zwischen Glaselementen |
Parameter spacing | Steuert den Merge-Abstand — Feineinstellung, wie nah Elemente sein müssen, um zu verschmelzen |
@Namespace + glassEffectID | Ermöglicht sanfte Morphing-Übergänge bei Änderungen der Ansichtshierarchie |
Modifikator interactive() | Explizites Opt-in für Berührungs-/Pointer-Reaktionen — nicht jedes Glas sollte reagieren |
| UIGlassContainerEffect in UIKit | Gleiches Container-Muster wie in SwiftUI für Konsistenz |
| Akzentuierter Rendering-Modus in Widgets | System wendet getöntes Glas an, wenn der Benutzer einen getönten Home-Bildschirm auswählt |
Best Practices
- Immer GlassEffectContainer verwenden, wenn Glas auf mehrere Geschwisteransichten angewendet wird — ermöglicht Morphing und verbessert die Rendering-Leistung
.glassEffect()nach anderen Darstellungsmodifikatoren (frame, font, padding) anwenden.interactive()nur auf Elemente anwenden, die auf Benutzerinteraktion reagieren (Schaltflächen, umschaltbare Elemente)- Abstand in Containern sorgfältig wählen, um zu steuern, wann Glaseffekte verschmelzen
withAnimationverwenden, wenn die Ansichtshierarchie geändert wird, um sanfte Morphing-Übergänge zu ermöglichen- Auf verschiedenen Darstellungen testen — heller Modus, dunkler Modus und akzentuierte/getönte Modi
- Barrierefreiheitskontrast sicherstellen — Text auf Glas muss lesbar bleiben
Anti-Patterns vermeiden
- Mehrere eigenständige
.glassEffect()-Ansichten ohne GlassEffectContainer verwenden - Zu viele Glaseffekte verschachteln — verschlechtert Leistung und visuelle Klarheit
- Glas auf jede Ansicht anwenden — für interaktive Elemente, Symbolleisten und Karten reservieren
clipsToBounds = truein UIKit bei Verwendung von abgerundeten Ecken vergessen- Akzentuierten Rendering-Modus in Widgets ignorieren — unterbricht die getönte Home-Bildschirmdarstellung
- Deckende Hintergründe hinter Glas verwenden — macht den Transluzenzeffekt zunichte
Wann verwenden
- Navigationsleisten, Symbolleisten und Registerkartenleisten mit dem neuen iOS 26 Design
- Schwebende Aktionsschaltflächen und kartenartige Container
- Interaktive Steuerelemente, die visuelle Tiefe und Berührungsfeedback benötigen
- Widgets, die in das Liquid Glass-Erscheinungsbild des Systems integriert werden sollen
- Morphing-Übergänge zwischen verwandten UI-Zuständen