← Alle Beitrage

Liquid Glass in SwiftUI: Drei Muster aus dem Release von Return auf iOS 26

Apples Liquid Glass ist eine einzeilige SwiftUI-API: .glassEffect().1 Return, mein Meditations-Timer, verwendet sie neunmal über iOS, macOS und tvOS hinweg.2 Eine dieser Verwendungen wendet den Modifier auf eine benutzerdefinierte Shape an, die die Timer-Zahlen selbst in flüssiges Glas verwandelt, Glyphe für Glyphe.

Return auf dem iPhone zeigt die Liquid-Glass-Timer-Zahlen, die den Fire-Theme-Hintergrund brechen, mit dem Dauer-Picker als Glas-HUD darunter

Die interessante Frage ist, was passiert, wenn man über den Einzeiler hinausgeht. Apples Human Interface Guidelines legen eine strikte Schichtungsregel fest: Liquid Glass gehört in die funktionale Schicht (Steuerelemente, Navigation, transiente UI) und niemals in die Inhaltsschicht.3 Die meisten der neun Verwendungen in Return sind klassische Anwendungen der funktionalen Schicht: Picker, Buttons, Control-Strips, Badges für den pausierten Zustand. Die interessanten Verwendungen sind die drei, die die Regeln biegen, ohne sie zu brechen.

Dieser Essay arbeitet drei Muster durch, die ich ausgeliefert habe, die Regeln, die sie respektieren, die Fallstricke, in die ich getappt bin, und die API-Oberfläche, die ich bewusst nicht verwendet habe.

TL;DR

  • iOS 26 liefert Liquid Glass als .glassEffect(_:in:) aus. Die Standard-Variante ist .regular und die Standardform ist Capsule.1
  • Return verwendet drei Muster, die über den Einzeiler hinausgehen: Glas auf einer benutzerdefinierten Shape (Timer-Text via Core Text Glyph Paths), das Spiegel-Muster (Reflexion darunter via gespiegelter und maskierter Kopie) und HUD-Overlays in der funktionalen Schicht.
  • Apples HIG-Regel: Liquid Glass für die funktionale Schicht, Standard-Materialien für die Inhaltsschicht.3
  • Ich habe GlassEffectContainer bewusst nicht verwendet. Die Morph-API hat keinen Anwendungsfall in Return (kein Glas-Element animiert sich in ein anderes hinein), und ich habe die Lücke in der Rendering-Performance nicht gemessen; dies ist ein ungemessener Trade-off, keine Empfehlung.1
  • Fallstricke: Glas auf einem flachen Hintergrund wirkt flach; jitter-freies Rendering der Ziffern erfordert Zellen mit fester Breite; tvOS’ HStack ignoriert den Layout-Direction-Environment-Wert; Reduce-Motion muss bei der Morph-Animation respektiert werden.

Die einzeilige API und die Schichtungsregel

Apple liefert Liquid Glass mit einer kleinen Oberfläche aus, eingeführt als wichtige Design-Säule auf der WWDC 2025:113

Text("Hello, World!")
    .font(.title)
    .padding()
    .glassEffect()                              // default: .regular variant, Capsule shape

Text("Hello, World!")
    .glassEffect(in: .rect(cornerRadius: 16))   // custom shape

Text("Hello, World!")
    .glassEffect(.regular.tint(.orange).interactive())  // tint + touch reactivity

Drei Stellschrauben: Variante (.regular oder .clear), Form (jede beliebige Shape) und eine GlassEffectStyle-Kette (Tint, Interactive). Das ist die gesamte API für eine einzelne View. Multi-View-Rendering wird von einem separaten GlassEffectContainer gehandhabt, auf den ich noch zu sprechen komme.

Die HIG ist enger gefasst als die API. Apples Human Interface Guidelines definieren zwei Schichten in jeder iOS-26+-Oberfläche:3

  1. Die Inhaltsschicht: das Dokument, die Liste, das Foto oder das Medium, das eine Person konsumiert. Verwenden Sie hier Standard-Materialien (die existierenden .regularMaterial, .thinMaterial etc.).
  2. Die funktionale Schicht: Steuerelemente, Navigation, Tab-Bars, Sidebars, transiente Overlays. Verwenden Sie hier Liquid Glass.

Apples konkrete Anweisung: „Don’t use Liquid Glass in the content layer. Liquid Glass works best when it provides a clear distinction between interactive elements and content, and including it in the content layer can result in unnecessary complexity and a confusing visual hierarchy.”3

Die Regel klingt restriktiv, bis Sie sie auf eine echte App abbilden. Return ist ein Meditations-Timer. Die Inhaltsschicht ist die Atembildsprache und das Loop-Video, das hinter allem läuft. Die funktionale Schicht ist der Dauer-Picker, der Start/Pause/Stop-Button-Stack, die sekundäre Settings-Button-Reihe und (auf tvOS) das Badge für den pausierten Zustand. Acht der neun Glas-Verwendungen in Return sind klassische Anwendungen der funktionalen Schicht: drei Dauer-Picker-Varianten für iOS- und macOS-Code-Pfade, der Start/Pause-Toggle, der Stop-Button, die Settings-Button-Reihe, der tvOS-Pause-Indikator und ein weiteres transientes Control-Overlay.4

Die neunte ist der bewusste Grenzfall (Liquid Glass auf den Timer-Zahlen selbst), den der nächste Abschnitt durcharbeitet.

Muster 1: Glas auf einer benutzerdefinierten Shape

Die Timer-Zahlen in Return sind kein Text, der über einen Glashintergrund gezeichnet wird. Das Glas ist der Text. .glassEffect(.clear, in:) akzeptiert jede beliebige Shape,9 und eine Shape ist ein Path-erzeugendes Protokoll.10 Der Trick lautet also: Den Timer-String mit Core Text in einen Glyphenpfad umwandeln,11 und dann diesen Pfad-als-Shape an .glassEffect übergeben.56

import SwiftUI
@preconcurrency import CoreText

struct GlassTextShape: Shape {
    let text: String
    let font: CTFont

    func path(in rect: CGRect) -> Path {
        guard !text.isEmpty else { return Path() }
        let combinedPath = CGMutablePath()

        let attrString = NSAttributedString(string: text, attributes: [.font: font])
        let line = CTLineCreateWithAttributedString(attrString)
        guard let runs = CTLineGetGlyphRuns(line) as? [CTRun], !runs.isEmpty else {
            return Path()
        }

        for run in runs {
            let glyphCount = CTRunGetGlyphCount(run)
            guard glyphCount > 0 else { continue }
            var glyphs = [CGGlyph](repeating: 0, count: glyphCount)
            var positions = [CGPoint](repeating: .zero, count: glyphCount)
            let range = CFRange(location: 0, length: glyphCount)
            CTRunGetGlyphs(run, range, &glyphs)
            CTRunGetPositions(run, range, &positions)

            for i in 0..<glyphCount {
                guard let glyphPath = CTFontCreatePathForGlyph(font, glyphs[i], nil) else { continue }
                let transform = CGAffineTransform(translationX: positions[i].x, y: positions[i].y)
                combinedPath.addPath(glyphPath, transform: transform)
            }
        }

        // Core Text y-axis is flipped vs SwiftUI; flip then re-bound and center.
        var swiftPath = Path(combinedPath).applying(CGAffineTransform(scaleX: 1, y: -1))
        let flippedBounds = swiftPath.boundingRect
        let offsetX = rect.midX - flippedBounds.midX
        let offsetY = rect.midY - flippedBounds.midY
        return swiftPath.applying(CGAffineTransform(translationX: offsetX, y: offsetY))
    }
}

Echter Produktionscode aus Return/Return/GlassTextShape.swift.5 Die Funktion path(in:) verwendet Core Text, um den String zu setzen, durchläuft jeden CTRun, extrahiert den CGPath jeder Glyphe und vereint sie zu einem einzigen CGMutablePath. Die zwei nicht offensichtlichen Schritte kommen nach der Vereinigung: Das Koordinatensystem von Core Text platziert den Ursprung unten links, während SwiftUIs Path ihn oben links setzt, sodass der Pfad via CGAffineTransform(scaleX: 1, y: -1) gespiegelt werden muss. Anschließend hat das boundingRect des gespiegelten Pfades negative y-Werte, sodass eine Translation ihn innerhalb des Rechtecks neu zentriert, das SwiftUI an die Shape übergibt. Lassen Sie eine der beiden Transformationen weg, und die Glyphen werden auf dem Kopf oder außerhalb des Bildschirms gerendert.

Die Anwendung ist dann eine einzige Zeile:

Rectangle()
    .fill(.clear)
    .glassEffect(.clear, in: textShape)
    .frame(width: cellWidth, height: cellHeight)

Das durchsichtige Rectangle ist ein Hit-Target-Platzhalter; das eigentliche Visuelle ist, was auch immer textShape produziert. Mit einer Glyph-Path-Shape füllt das Liquid-Glass-Material nur die Glyphen-Konturen. Das Ergebnis: Jede Ziffer des Timers ist eine separate Liquid-Glass-Form, die jede Animation bricht, die hinter ihr läuft.6

Die HIG-Nuance. Apples explizite Regel lautet Liquid Glass für die funktionale Schicht, Standard-Materialien für die Inhaltsschicht, mit einer ausdrücklichen Ausnahme: transiente interaktive Steuerelemente in der Inhaltsschicht (Slider, Toggles) können Liquid Glass annehmen, wenn sie aktiviert werden.3 Die Timer-Zahlen in Return sind eine Zustandsanzeige, kein Steuerelement: Sie aktualisieren sich einmal pro Sekunde aus Timer.publish(every: 1, ...) und haben keine Tap-Geste (der Start/Pause-Button darunter ist es, der den Zustand umschaltet). Liquid Glass auf sie zu legen, ist also ein bewusster Grenzfall, der intentional näher an einem „transienten interaktiven Steuerelement” liegt als an wörtlicher Interaktivität, denn die Zahlen sind der visuelle Fokuspunkt, den Benutzer die gesamte Sitzung über betrachten. Ich biege die Regel, ich breche sie nicht. Ein Reviewer, der die HIG strikt liest, könnte argumentieren, dass dies ein Standard-Material sein sollte; ich argumentiere, dass der Timer eine Zeit-verstrichen-Steuerfläche in derselben Familie wie ein Fortschrittsindikator ist. Apples Dokumentation entscheidet den Fall nicht direkt.

Warum eine benutzerdefinierte Shape statt Text + Hintergrund. Text, der über einem Glashintergrund gerendert wird, wirkt als Text auf Glas. Text, der als Glas selbst gerendert wird, wirkt als eine andere visuelle Kategorie. Der Benutzer nimmt die Zahlen als funktionalen Vordergrund wahr, konkret als ein transientes Element, das existiert, um hindurchgesehen zu werden, nicht angesehen.

Muster 2: Das Spiegel-Muster

Return zeigt eine Reflexion des Timers darunter, die ausblendet. Echter Produktionscode:6

Return auf dem Mac zeigt den Dauer-Picker als Liquid-Glass-HUD-Overlay, mit der Glasbehandlung des Timer-Textes darüber sichtbar

VStack(spacing: 0) {
    GlassTimerText(text: displayTime, fontSize: fontSize)
        .accessibilityLabel("Time remaining: \(accessibleDescription)")

    if showReflection {
        GlassTimerText(text: displayTime, fontSize: fontSize)
            .scaleEffect(x: 1, y: -1)
            .mask(
                LinearGradient(
                    stops: [
                        .init(color: .white.opacity(0.2), location: 0),
                        .init(color: .clear, location: 0.6)
                    ],
                    startPoint: .top,
                    endPoint: .bottom
                )
            )
            .offset(y: -8)
            .accessibilityHidden(true)
    }
}

Drei Transformationen setzen den Spiegel zusammen, alle Standard-SwiftUI-Primitive:14

  1. scaleEffect(x: 1, y: -1) dreht die zweite Kopie auf den Kopf.
  2. .mask(LinearGradient(...)) blendet die Reflexion von 20 % Deckkraft oben zu vollständig transparent bei 60 % nach unten aus.
  3. .offset(y: -8) zieht die Reflexion 8 Punkte nach oben, sodass sie am Original anliegt, anstatt eine sichtbare Naht zu hinterlassen.

Der Modifier .accessibilityHidden(true) auf der Reflexion ist tragend. VoiceOver soll die gespiegelte Zeit nicht zweimal ansagen; das accessibilityLabel und accessibilityAddTraits(.updatesFrequently) des Originals sind bereits an die Haupt-GlassTimerText-Instanz darüber angehängt, und die Reflexion ist rein dekorativ.

Warum das speziell mit Liquid Glass funktioniert. Die Reflexion erbt das Glasmaterial von GlassTimerText. Jeder Hintergrund, auf dem das Original sitzt (ein Atemkreis-Verlauf, ein Video, eine getönte Szene), bricht durch beide Kopien. Der Spiegel braucht keinerlei glas-spezifischen Code; das Glasmaterial übernimmt die Brechung kostenlos. Der gesamte Effekt sind drei Modifier und ein Verlauf.

Die Barrierefreiheits-Kosten. Reduce-Motion-Benutzer sehen den Spiegel weiterhin, aber die Animation des Glasmaterials zwischen den Zeit-Updates wird an anderer Stelle via @Environment(\.accessibilityReduceMotion) unterdrückt.7 Die Reflexion selbst ist statisch; nur das Morphing zwischen den Ziffern-Übergängen wird animiert.

Muster 3: Glas-HUD-Overlays für transiente Steuerelemente

Die verbleibenden acht Glas-Verwendungen in Return sind klassische Anwendungen der funktionalen Schicht.4 Jede folgt demselben Muster:

Return auf der Apple Watch zeigt Liquid Glass der funktionalen Schicht auf dem Start/Pause-Steuerelement bei kleiner Canvas-Größe

durationPicker
    .frame(height: 50)
    .frame(maxWidth: 320)
    .glassEffect()
    .padding(.horizontal, 20)
    .transition(.opacity.combined(with: .scale(scale: 0.95)))

Der .transition(.opacity.combined(with: .scale(scale: 0.95))) ist der tragende Teil. Liquid Glass auf transienten Steuerelementen fühlt sich nur dann richtig an, wenn die Steuerelemente auch transitieren. Ein statisches Glas-HUD, das permanent auf dem Bildschirm sitzt, wirkt als Chrome. Ein Glas-HUD, das einblendet und einscaliert, wenn der Benutzer tippt, und ausblendet, wenn er wegblickt, wirkt als momentane Steuerfläche.

Apples Dokumentation zu glassEffect merkt das implizit an: Der Modifier „captures the content to send to the container to render” und „react[s] to touch and pointer interactions in real time.”1 Die Animations-Hooks sind nicht in der API, aber die Rendering-Pipeline geht davon aus, dass sich Glas-Elemente bewegen. Statische Glas-Elemente verfehlen diese Affordanz.

Return verwendet das Muster für den Dauer-Picker (gleitet hoch, wenn der Benutzer tippt), den Start/Pause-Toggle-Button (immer sichtbar, scaliert aber bei Druck), den Stop-Button (nur mitten in der Sitzung sichtbar), die Settings-Button-Reihe (ein horizontaler Control-Strip unter dem Dauer-Picker) und das tvOS-Badge für den pausierten Zustand (nur sichtbar, wenn eine Sitzung auf Apple TV pausiert ist). Alle fünf Kontexte respektieren die Funktional-Schicht-Regel der HIG.3

Return auf dem Apple TV zeigt die Liquid-Glass-Behandlung skaliert für eine 10-Fuß-Oberfläche

Die GlassEffectContainer-Frage

Apple empfiehlt GlassEffectContainer immer dann, wenn eine App .glassEffect() auf mehreren Views verwendet, aus zwei Gründen: bessere Rendering-Performance (Glaseffekte werden gebatched) und die Fähigkeit, Formen während Übergängen ineinander zu morphen.1

Ich habe ihn nicht verwendet. Die Begründung ist anwendungsspezifisch, keine Widerlegung von Apples Leitlinie. Return hat neun Glas-Views, von denen keiner zwischen einem anderen morphen muss.46 Der Dauer-Picker animiert sich nie in den Start-Button hinein. Der Timer-Text animiert sich nie in die Settings-Button-Reihe hinein. Jedes Glas-Element ist unabhängig. Die Morph-API hätte keinen Anwendungsfall, auf den sie feuern könnte, und die Spacing-Regeln des Containers würden Layouts einschränken, die heute keine Koordination benötigen.

Das Argument der Rendering-Performance kann ich ohne Messung nicht vollständig widerlegen. Apples Dokumentation warnt, dass „too many” Glaseffekte außerhalb eines Containers die Performance verschlechtern können.1 Die neun Views von Return teilen sich nie gleichzeitig den Bildschirm (der Dauer-Picker erscheint nur im Menüzustand, der Stop-Button nur, wenn mitten in der Sitzung pausiert wird). Bei jedem gegebenen Frame zähle ich drei oder vier sichtbare Glas-Elemente, was auf jedem Gerät, das ich über iOS, iPadOS, macOS, watchOS und tvOS hinweg getestet habe, flüssig war, aber ich habe keinen Instruments-Trace gefahren, der Container-umhüllt gegen Modifier-only vergleicht. Daher die ehrliche Einordnung: Return überspringt GlassEffectContainer auf Basis einer beobachteten guten Benutzererfahrung, nicht einer gemessenen Performance-Äquivalenz.

Die Regel, die ich daraus gezogen habe: GlassEffectContainer ist für Apps, in denen mehrere Glas-Elemente gleichzeitig sichtbar sind und animieren. Apples Beispiel ist Symbol-Set-Rendering mit glassEffectUnion(id:namespace:): vier Wettersymbole, die als Einheit fließend verschmelzen und sich teilen.1 Das ist ein klassischer Anwendungsfall. Wenn ein zukünftiges Return-Feature Glas-Elemente benötigt, die morphen oder sich die Spacing-Regeln eines Containers teilen, ist der Container das richtige Werkzeug, um es dann hinzuzufügen. Für die heutige App bin ich diesem Fall noch nicht begegnet.

Die Fallstricke, in die ich getappt bin

Drei echte Bugs aus der Produktion:

Glas-Ziffern-Jitter. SF Pro Rounded hat im proportionalen Rendering Ziffern variabler Breite. Während der Timer rückwärts zählte, änderte sich die Länge des angezeigten Strings, und der umgebende HStack floss jede Sekunde neu, wodurch der gesamte Timer ruckelte. Die Lösung: Zellen mit fester Breite für jedes Zeichen. Jede Ziffer erhält eine cellWidth von fontSize * 0.6, jeder Doppelpunkt erhält fontSize * 0.3, und der HStack wird zu einem stabilen Raster.6

HStack(spacing: 0) {
    ForEach(Array(text.enumerated()), id: \.offset) { _, char in
        let isColon = char == ":"
        let cellWidth = isColon ? colonCellWidth : digitCellWidth
        GlassDigitCell(character: String(char), font: ctFont,
                       cellWidth: cellWidth, cellHeight: cellHeight)
    }
}

Die Zellen sind nicht Apple-Standard; sie sind ein Workaround für proportionales Rendering bei kleinen festen Schriftgrößen. Apples SF Pro Rounded mit .monospacedDigit() würde dasselbe Problem auf Text lösen, aber der Modifier ist auf einem benutzerdefinierten Shape-basierten Glas-Renderer nicht verfügbar. Das Layout mit festen Zellen ist der Ersatz.

tvOS Layout-Direction-Override. Derselbe GlassTimerText lief auf iOS, iPadOS, macOS und tvOS. Speziell auf tvOS spiegelte sich der HStack unter einer Right-to-Left-Sprachumgebung, obwohl die iOS-Version den In-Environment-Override respektierte. Die Lösung: Layout-Richtung sowohl über den Environment-Wert als auch über den expliziten flipsForRightToLeftLayoutDirection(false)-Modifier festschreiben, direkt auf den HStack der Ziffern-Zellen angewendet (der übergeordnete VStack wendet den Environment-Override separat an, sodass die Reflexionskopie ihn erbt):6

HStack(spacing: 0) { ... }
    .flipsForRightToLeftLayoutDirection(false)
    .environment(\.layoutDirection, .leftToRight)

Der Grund: tvOS’ HStack scheint den Override auf Environment-Ebene in einigen Versionen zu ignorieren, und flipsForRightToLeftLayoutDirection(false) ist der explizite Kein-Spiegel-Vertrag, der zuverlässiger respektiert wird.12 Hosenträger und Gürtel.

Reduce-Motion auf dem Ziffern-Morph. Liquid Glass animiert standardmäßig Morph-Übergänge zwischen angezeigten Strings. Benutzer mit aktiviertem accessibilityReduceMotion sahen den Morph als Flackern. Die Lösung:6

.animation(reduceMotion ? nil : .easeInOut(duration: 0.15), value: displayTime)

Der Animations-Modifier liest @Environment(\.accessibilityReduceMotion) und deaktiviert den Übergang vollständig, wenn Reduce-Motion aktiv ist. Apples Barrierefreiheits-Leitlinie ist explizit: Jede dekorative Animation muss die Bewegungs-Präferenz des Benutzers respektieren.7

Wann Sie Liquid Glass nicht verwenden sollten

Verzicht ist Teil des Designs.

Setzen Sie Liquid Glass nicht in die Inhaltsschicht. Apples HIG ist explizit, und das Ignorieren der Regel erzeugt eine verwirrende Hierarchie: Der Benutzer kann nicht erkennen, was interaktiv ist und was Inhalt.3 Wenn ein Glaseffekt eine Listenzeile oder eine Foto-Karte schmückt, kämpft das Design gegen die Plattform.

Verwenden Sie Glas nicht über einem flachen Hintergrund. Liquid Glass bricht das, was dahinter ist. Wenn „das, was dahinter ist”, eine einzige Volltonfarbe ist, hat die Brechung nichts zu beugen, und das Ergebnis wirkt als flaches getöntes Rechteck. Setzen Sie Glas entweder über variierten Inhalt (einen Verlauf, ein Bild, ein Video) oder verwenden Sie überhaupt kein Glas. Der Timer-Bildschirm von Return rendert Theme-basierte Cover-Bildsprache und Loop-Video als Hintergrund über VideoBackgroundView,4 gerade damit die Glas-Elemente darüber immer Textur zum Brechen haben.

Seien Sie vorsichtig mit Glas auf hochfrequentem Inhalt. Das Rendering des Glasmaterials ist GPU-gebunden, und die Standard-Morph-Animation zwischen Glasform-Änderungen ist selbst eine Animation. Ein Timer, der sich einmal pro Sekunde aktualisiert, ist in meinen Tests in Ordnung; eine Wellenform oder ein Audio-Visualizer mit 60 Hz ist nicht erprobt und kämpft wahrscheinlich gegen die Morph-Animation. Ich habe die obere Grenze nicht gemessen; behandeln Sie dies als Heuristik, nicht als gemessene Schwelle. Apples Dokumentation veröffentlicht keine.

Liefern Sie Glas nicht aus, ohne Reduce-Motion zu testen. Jede Glas-Animation sollte auf accessibilityReduceMotion gegated sein.7 Der Standard-Morph zwischen Glasformen ist ein kinetischer Effekt, nicht nur ein Fade.

Was Liquid Glass für Apps bedeutet, die auf iOS 26+ ausgeliefert werden

Die These ist klein. Liquid Glass ist nur dann eine einzeilige API, wenn die App die HIG-Schichtungsregel bereits respektiert. Eine SwiftUI-App, die Steuerelemente in die funktionale Schicht und Inhalt in die Inhaltsschicht legt, kann Liquid Glass mit .glassEffect()-Modifiern adoptieren und sich standardmäßig nativ anfühlen.

Apps, die die beiden Schichten vermischen (Steuerelemente innerhalb von Listenzeilen, Navigationsleisten, die als Inhalt behandelt werden, dekoratives Chrome auf Foto-Karten), werden Liquid Glass adoptieren und sich falsch anfühlen. Das Material ist korrekt; die Architektur darunter nicht.

Das Custom-Shape-Muster (Muster 1) erweitert die Regel sauber. Alles, was funktional ein Steuerelement ist, kann Liquid Glass annehmen, selbst wenn es nicht wie ein „Steuerelement” im konventionellen Sinne aussieht. Ein Timer ist ein Steuerelement, ein Pegelmesser ist ein Steuerelement, ein Fortschrittsindikator ist ein Steuerelement. Liquid Glass auf jedem davon ist on-spec.

Lesen Sie diesen Beitrag zusammen mit meinen früheren Aufsätzen über das Ausliefern derselben App-Datenschicht über App Intents und über einen MCP-Server. Die visuelle Schicht ist die dritte Oberfläche desselben Stacks: typisierte Entitäten für System-KI, Dateiformat für plattform-LLM-Agenten und Liquid Glass für den Menschen am Gerät.8

FAQ

Kann ich .glassEffect() auf nicht-iOS-26-Plattformen verwenden?

Der Modifier .glassEffect() ist iOS 26+, iPadOS 26+, macOS 26+, watchOS 26+, tvOS 26+, visionOS 26+. Plattformen vor 26 haben .background(.regularMaterial) und Ähnliches, was Frosted-Glass-Effekte produziert, aber nicht die neue Liquid-Glass-Brechung.1

Verändert GlassEffectContainer das Visuelle?

In einem Container umhüllte Glas-Elemente können ihre Formen miteinander verschmelzen, wenn ihre Spacing-Regeln eine Überlappung verursachen. Ohne Container ist jeder .glassEffect() unabhängig. Für Apps, in denen Glas-Elemente während der Animation fließend verschmelzen sollen, ist GlassEffectContainer das richtige Werkzeug. Für Apps, in denen jedes Glas-Element distinkt bleibt, ist ein Container Overhead.1

Warum nicht direkt Text mit .foregroundStyle(.thinMaterial) verwenden?

thinMaterial ist ein Standard-Material, kein Liquid Glass. Das Visuelle ist ein Frosted-Glass-Overlay, nicht der refraktive Glas-mit-Lichtbrechungs-Effekt von Liquid Glass.3 Für Text, der speziell wie das neue Material aussehen soll, ist .glassEffect(.clear, in: customShape) der unterstützte Pfad.

Wie nehme ich einen Liquid-Glass-Screenshot für Marketing auf?

Glaseffekte werden zur Laufzeit GPU-gerendert, sodass Screenshots vom Simulator oder Gerät mit bereits angewendetem Effekt aufgenommen werden. Apples offizielle Liquid-Glass-Referenzbildsprache stammt aus den Seiten der HIG-Dokumentation und den WWDC-2025-Sessions.3

Funktioniert GlassTextShape für beliebigen Text oder nur für Ziffern?

Jeder String, den Core Text setzen kann, funktioniert. Return verwendet sie für Ziffern und einen Doppelpunkt, aber dieselbe Shape funktioniert für Buchstaben, Symbole, Emojis (mit der richtigen Schriftart) oder gemischte Strings. Die Performance ist durch die Glyphenanzahl begrenzt; ein langer Absatz, der als Glas gerendert wird, wäre teuer, aber ein sechs Zeichen langer Timer ist trivial.


Drei Muster, eine Regel und eine API, die ich bewusst übersprungen habe. Liquid Glass ist die dritte Oberfläche einer iOS-26+-App, die auf typisierten Entitäten und gemeinsam genutzten Dateiformaten aufsitzt. Die einzeilige API ist real. Die HIG-Regel darunter ist es, die den Einzeiler funktionieren lässt.

Referenzen


  1. Apple Developer, “Applying Liquid Glass to custom views”. Dokumentation für den Modifier glassEffect(_:in:), GlassEffectContainer, glassEffectUnion(id:namespace:), glassEffectID(_:in:) und GlassEffectTransition. Standard-Variante .regular, Standardform Capsule

  2. Return des Autors, eine Meditations-Timer-App, die am 21. April 2026 im App Store veröffentlicht wurde, verfügbar für iPhone, iPad, Mac, Apple Watch und Apple TV. Verwendet SwiftUI, SwiftData und HealthKit auf iOS 26+ / macOS 26+. 

  3. Apple Developer, “Materials” Human Interface Guidelines. Definiert die Funktional-vs-Inhalts-Schicht-Regel für Liquid Glass: „Don’t use Liquid Glass in the content layer.” Listet die Varianten Regular und Clear sowie ihre vorgesehenen Verwendungen auf. 

  4. Produktionscode in Return/Return/ContentView.swift (sieben .glassEffect()-Aufrufstellen), Return/Return/GlassTimerText.swift (eine Aufrufstelle auf GlassDigitCell) und Return/ReturnTV/TVContentView.swift (eine Aufrufstelle auf dem tvOS-„Paused”-Indikator). Insgesamt neun. Plus Return/Return/VideoBackgroundView.swift, das die Theme-basierte Cover-Bildsprache und das Loop-Video rendert, durch das die Glas-Elemente brechen. 

  5. Produktionscode in Return/Return/GlassTextShape.swift. Der Shape-konforme Wrapper um Core Text. Erstellt am 26. November 2025, enthalten in der ausgelieferten App-Store-Version 1.0. 

  6. Produktionscode in Return/Return/GlassTimerText.swift. Views GlassDigitCell, GlassTimerText und GlassTimerDisplay. Implementiert das Zell-Layout mit fester Breite, die Spiegelreflexion und das Reduce-Motion-Gating. 

  7. Apple Developer, Environment-Wert “accessibilityReduceMotion”. Apps müssen die Bewegungs-Präferenz des Benutzers respektieren; Standard-Morph-Animationen auf Liquid Glass sollten auf den Wert gegated sein. 

  8. Analyse des Autors in App Intents Are Apple’s New API to Your App und Two Agent Ecosystems, One Shopping List. Das Drei-Oberflächen-Modell: App Intents für Apple Intelligence, MCP für plattform-LLM-Agenten, Liquid Glass für den Menschen am Gerät. 

  9. Apple Developer, “glassEffect(_:in:isEnabled:)” auf View. Der Parameter in: akzeptiert jeden Shape-konformen Typ. Die Standardform ist Capsule

  10. Apple Developer, Protokoll “Shape”. Eine Shape ist jeder Typ, der einen Path für ein gegebenes Rechteck produziert. Benutzerdefinierte Shapes können beliebige CGPath-Daten umhüllen. 

  11. Apple Developer, “Core Text Programming Guide” und CTLineCreateWithAttributedString. Core Text ist die niedrigerstufige Text-Engine, die verwendet wird, um attributierte Strings in Glyphen-Runs zu setzen und Pfade pro Glyphe zu extrahieren. 

  12. Apple Developer, “flipsForRightToLeftLayoutDirection(_:)”. Überschreibt die RTL-Spiegelung auf einer View explizit, unabhängig vom umgebenden Environment-Wert \.layoutDirection

  13. Apple, “WWDC 2025 Highlights” via Apple Newsroom. Liquid Glass angekündigt als das vereinheitlichende Design-Material über iOS 26, iPadOS 26, macOS 26, watchOS 26, tvOS 26 und visionOS 26 hinweg. Sessions: “Meet Liquid Glass” (WWDC 2025), “Build a SwiftUI app with Liquid Glass”

  14. Apple Developer, “LinearGradient”, “scaleEffect(x:y:anchor:)”, “mask(_:)”. Standard-SwiftUI-Primitive, alle seit iOS 13 verfügbar. 

Verwandte Beiträge

HealthKit + SwiftUI auf iOS 26: Autorisierung, Sample-Typen und plattformübergreifende Muster aus zwei ausgelieferten Apps

Echte Produktionsmuster aus Water (Wassertracking, HKQuantitySample) und Return (Achtsamkeitssitzungen, HKCategorySample…

13 Min. Lesezeit

SwiftUI Layout-Protokoll: Eigene Layouts mit sizeThatFits und placeSubviews entwickeln

Mit dem Layout-Protokoll von iOS 16 können Apps eigene Layouts mit zwei Methoden erstellen. sizeThatFits, placeSubviews,…

11 Min. Lesezeit

Geschmack ist Infrastruktur

Da Agenten immer mehr von dem generieren, was ausgeliefert wird, bestimmt die Qualität Ihrer ästhetischen Urteilskodieru…

6 Min. Lesezeit