Liquid Glass w SwiftUI: trzy wzorce z wdrożenia Return na iOS 26
Liquid Glass od Apple to jednoliniowe API SwiftUI: .glassEffect().1 Return, mój timer do medytacji, używa go dziewięć razy w iOS, macOS i tvOS.2 Jedno z tych zastosowań nakłada modyfikator na niestandardowy Shape, który zamienia same cyfry timera w liquid glass, glif po glifie.

Ciekawe pytanie brzmi: co dzieje się, gdy wykracza się poza ten jeden wiersz. Wytyczne Human Interface Guidelines od Apple wyznaczają ścisłą regułę warstwowania: Liquid Glass należy do warstwy funkcjonalnej (kontrolki, nawigacja, przejściowe UI), a nigdy do warstwy treści.3 Większość z dziewięciu zastosowań w Return to podręcznikowe aplikacje warstwy funkcjonalnej: selektory, przyciski, paski kontrolne, plakietki stanu wstrzymania. Ciekawe są te trzy, które naginają reguły, nie łamiąc ich.
Ten esej omawia trzy wzorce, które wdrożyłem, reguły, których przestrzegają, pułapki, które mnie złapały, oraz powierzchnię API, której świadomie nie wykorzystałem.
Wytyczne Human Interface Guidelines od Apple definiują Liquid Glass przez trzy warianty materiału. Wariant regular dostosowuje swój wygląd do tego, co znajduje się pod nim (przykład po lewej — ciemny; przykład po prawej — jasny); wariant clear pozwala szczegółom spod spodu prześwitywać przy znacznie mniejszym filtrowaniu:3



Obrazy referencyjne ze strony Materials HIG od Apple.3 Oba warianty to dokładnie to, co .glassEffect() tworzy w SwiftUI; wybór między nimi to pojedynczy argument modyfikatora.
W skrócie
- iOS 26 dostarcza Liquid Glass jako
.glassEffect(_:in:). Domyślny wariant to.regular, a domyślny kształt toCapsule.1 - Return używa trzech wzorców wykraczających poza ten jeden wiersz: szkło na niestandardowym
Shape(tekst timera przez ścieżki glifów Core Text), wzorzec lustra (odbicie pod spodem dzięki odwróconej i zamaskowanej kopii) oraz nakładki HUD warstwy funkcjonalnej. - Reguła HIG od Apple: Liquid Glass dla warstwy funkcjonalnej, standardowe materiały dla warstwy treści.3
- Świadomie nie użyłem
GlassEffectContainer. API przekształcania nie ma zastosowania w Return (żaden element szkła nie animuje się w inny), a nie zmierzyłem różnicy w wydajności renderowania; jest to niezmierzony kompromis, a nie rekomendacja.1 - Pułapki: szkło na płaskim tle wygląda płasko; renderowanie cyfr bez drgań wymaga komórek o stałej szerokości;
HStackw tvOS ignoruje wartość środowiskową kierunku układu; animacja przekształcenia musi respektować redukcję ruchu.
W kontekście pokrewnych wzorców UI od Apple warto przeczytać szczegółową analizę protokołu układu SwiftUI, system typograficzny SF Pro oraz słownik Symbol Effects.
Jednoliniowe API i reguła warstwowania
Apple dostarcza Liquid Glass z niewielką powierzchnią, wprowadzony jako główny filar projektowy na 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
Trzy pokrętła: wariant (.regular lub .clear), kształt (dowolny Shape) oraz łańcuch GlassEffectStyle (zabarwienie, interaktywność). To całe API dla pojedynczego widoku. Renderowanie wielu widoków obsługuje oddzielny GlassEffectContainer, do którego jeszcze przejdę.
HIG jest bardziej rygorystyczny niż samo API. Wytyczne Human Interface Guidelines od Apple definiują dwie warstwy w każdym interfejsie iOS 26+:3
- Warstwa treści: dokument, lista, zdjęcie lub media, które ktoś konsumuje. Tutaj należy używać materiałów standardowych (istniejące
.regularMaterial,.thinMaterialitp.). - Warstwa funkcjonalna: kontrolki, nawigacja, paski kart, paski boczne, przejściowe nakładki. Tutaj należy używać Liquid Glass.
Konkretne zalecenie Apple: „Nie używaj Liquid Glass w warstwie treści. Liquid Glass sprawdza się najlepiej, gdy zapewnia wyraźne rozróżnienie między elementami interaktywnymi a treścią, a umieszczenie go w warstwie treści może skutkować zbędną złożonością i mylącą hierarchią wizualną.”3
Reguła brzmi restrykcyjnie, dopóki nie przeniesie się jej na rzeczywistą aplikację. Return to timer do medytacji. Jego warstwą treści jest obraz oddechu i zapętlony film, który płynie za wszystkim. Jego warstwą funkcjonalną jest selektor czasu trwania, stos przycisków start/pauza/stop, dodatkowy rząd przycisków ustawień, a (na tvOS) plakietka stanu wstrzymania. Osiem z dziewięciu zastosowań szkła w Return to podręcznikowe aplikacje warstwy funkcjonalnej: trzy warianty selektora czasu trwania dla ścieżek kodu iOS i macOS, przełącznik start/pauza, przycisk stop, rząd przycisków ustawień, wskaźnik wstrzymania na tvOS oraz jeszcze jedna przejściowa nakładka kontrolna.4
Dziewiąte to celowy przypadek graniczny (Liquid Glass na samych cyfrach timera), który omawia następna sekcja.
Wzorzec 1: szkło na niestandardowym Shape
Cyfry timera w Return to nie tekst narysowany na szklanym tle. Szkło jest tekstem. .glassEffect(.clear, in:) przyjmuje dowolny Shape,9 a Shape to protokół produkujący Path.10 Sztuczka polega więc na tym, aby przekonwertować ciąg timera na ścieżkę glifów przy użyciu Core Text,11 a następnie przekazać tę ścieżkę-jako-Shape do .glassEffect.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))
}
}
Rzeczywisty kod produkcyjny z Return/Return/GlassTextShape.swift.5 Funkcja path(in:) używa Core Text do rozłożenia ciągu, przechodzi przez każdy CTRun, wyciąga CGPath każdego glifu i łączy je w jeden CGMutablePath. Dwa nieoczywiste kroki następują po połączeniu: układ współrzędnych Core Text umieszcza początek w lewym dolnym rogu, podczas gdy Path w SwiftUI umieszcza go w lewym górnym, więc ścieżkę trzeba odwrócić przez CGAffineTransform(scaleX: 1, y: -1). Następnie boundingRect odwróconej ścieżki ma ujemne wartości y, więc translacja ponownie wyśrodkowuje ją wewnątrz prostokąta, który SwiftUI przekazuje do Shape. Pominięcie którejkolwiek z transformacji powoduje, że glify renderują się do góry nogami lub poza ekranem.
Następnie zastosowanie to pojedynczy wiersz:
Rectangle()
.fill(.clear)
.glassEffect(.clear, in: textShape)
.frame(width: cellWidth, height: cellHeight)
Przezroczysty Rectangle to wypełniacz celu dotyku; faktyczną wizualizacją jest dowolny kształt produkowany przez textShape. Przy kształcie ścieżki glifów materiał Liquid Glass wypełnia tylko kontury glifów. Rezultat: każda cyfra timera to oddzielna forma liquid glass, załamująca dowolną animację, która płynie za nią.6
Niuans HIG. Deklarowana reguła Apple to Liquid Glass dla warstwy funkcjonalnej, standardowe materiały dla warstwy treści, z jednym wyraźnym wyjątkiem: przejściowe interaktywne kontrolki w warstwie treści (suwaki, przełączniki) mogą przyjąć Liquid Glass po aktywacji.3 Cyfry timera w Return to wyświetlanie stanu, a nie kontrolka: aktualizują się raz na sekundę z Timer.publish(every: 1, ...) i nie mają gestu dotknięcia (to przycisk start/pauza pod nimi przełącza stan). Umieszczenie na nich Liquid Glass to więc celowy przypadek graniczny, bliższy „przejściowej interaktywnej kontrolce” z intencji niż z dosłownej interaktywności, ponieważ cyfry są wizualnym punktem skupienia, który użytkownicy obserwują przez całą sesję. Naginam regułę, nie łamię jej. Recenzent czytający HIG ściśle mógłby twierdzić, że powinien to być materiał standardowy; ja argumentuję, że timer to kontrolna powierzchnia upływu czasu z tej samej rodziny co wskaźnik postępu. Dokumentacja Apple nie rozstrzyga tego przypadku wprost.
Dlaczego niestandardowy Shape, a nie Text + tło. Text renderowany nad szklanym tłem czyta się jako tekst na szkle. Text renderowany jako samo szkło czyta się jako odmienna kategoria wizualna. Użytkownik postrzega cyfry jako funkcjonalny pierwszy plan, a konkretnie jako element przejściowy, który istnieje po to, by patrzeć przez niego, a nie na niego.
Wzorzec 2: wzorzec lustra
Return pokazuje pod timerem jego odbicie, które zanika. Rzeczywisty kod produkcyjny:6

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)
}
}
Trzy transformacje składają się na lustro, wszystkie standardowe prymitywy SwiftUI:14
scaleEffect(x: 1, y: -1)odwraca drugą kopię do góry nogami..mask(LinearGradient(...))wygasza odbicie od 20% nieprzezroczystości u góry do pełnej przezroczystości na 60% w dół..offset(y: -8)podciąga odbicie o 8 punktów w górę, aby przylegało do oryginału, zamiast pozostawiać widoczny szew.
Modyfikator .accessibilityHidden(true) na odbiciu jest nośnikiem znaczenia. VoiceOver nie powinien ogłaszać odbitego czasu dwukrotnie; accessibilityLabel oryginału oraz accessibilityAddTraits(.updatesFrequently) są już dołączone do głównej instancji GlassTimerText powyżej, a odbicie jest czysto dekoracyjne.
Dlaczego działa to właśnie z Liquid Glass. Odbicie dziedziczy materiał szkła z GlassTimerText. Każde tło, na którym znajduje się oryginał (gradient oddechowego okręgu, film, zabarwiona scena), załamuje się przez obie kopie. Lustro nie potrzebuje żadnego kodu specyficznego dla szkła; materiał szkła obsługuje załamanie za darmo. Cały efekt to trzy modyfikatory i gradient.
Koszt dostępności. Użytkownicy z redukcją ruchu nadal widzą lustro, ale animacja materiału szkła między aktualizacjami czasu jest tłumiona w innym miejscu przez @Environment(\.accessibilityReduceMotion).7 Samo odbicie jest statyczne; animuje się jedynie przekształcenie między zmianami cyfr.
Wzorzec 3: szklane nakładki HUD dla przejściowych kontrolek
Pozostałe osiem zastosowań szkła w Return to podręcznikowe aplikacje warstwy funkcjonalnej.4 Każde podąża za tym samym wzorcem:

durationPicker
.frame(height: 50)
.frame(maxWidth: 320)
.glassEffect()
.padding(.horizontal, 20)
.transition(.opacity.combined(with: .scale(scale: 0.95)))
Element .transition(.opacity.combined(with: .scale(scale: 0.95))) jest częścią nośną. Liquid Glass na przejściowych kontrolkach wygląda właściwie tylko wtedy, gdy te kontrolki przemijają. Statyczny szklany HUD, który stale tkwi na ekranie, czyta się jak chrom. Szklany HUD, który wygasza się i skaluje przy dotknięciu przez użytkownika i z powrotem znika, gdy ten odwraca wzrok, czyta się jako chwilowa powierzchnia kontrolna.
Dokumentacja Apple dotycząca glassEffect zauważa to pośrednio: modyfikator „przechwytuje treść, którą wysyła do kontenera do wyrenderowania” i „reaguje na interakcje dotykiem i wskaźnikiem w czasie rzeczywistym.”1 Zaczepów animacji nie ma w API, ale potok renderowania zakłada, że elementy szkła się poruszają. Statyczne elementy szkła tracą tę afordancję.
Return używa tego wzorca dla selektora czasu trwania (wysuwa się w górę, gdy użytkownik dotyka), przycisku przełącznika start/pauza (zawsze widoczny, ale skaluje się przy naciśnięciu), przycisku stop (widoczny tylko w trakcie sesji), rzędu przycisków ustawień (poziomy pasek kontrolny pod selektorem czasu trwania) oraz plakietki stanu wstrzymania na tvOS (widoczna tylko, gdy sesja jest wstrzymana na Apple TV). Wszystkie pięć kontekstów respektuje regułę warstwy funkcjonalnej z HIG.3

Materiał referencyjny Apple HIG: nakładki Liquid Glass w tvOS znajdują się nad warstwą mediów, pozwalając im prześwitywać.3 Implementacja tvOS w Return podąża za tym samym modelem: kontrolki unoszą się nad zapętlonym tłem ognia/lasu/wody.
Uwaga o pasku narzędzi z laboratoriów. Panel WWDC 2026 SwiftUI Group Lab doprecyzował, jak wygląda to w paskach narzędzi. Umieszczenie nieszklanej treści w pasku narzędzi — przykładem było zdjęcie profilowe — wymaga sharedBackgroundVisibility(.hidden), aby element porzucił współdzielone szklane tło i pokazał zdjęcie bezpośrednio.15 Panel zwrócił uwagę na pewną subtelność: nowsze API usuwa jedynie margines treści przycisku paska narzędzi, podczas gdy wcześniej ukrycie tła było jedyną dźwignią i usuwało jednocześnie zarówno tło, jak i margines. Dla samych przycisków paska narzędzi panel skierował uwagę w stronę wyróżnionego stylu przycisku (glassProminent) i buttonBorderShape, zamiast sięgać po .glassEffect bezpośrednio na przycisku. Leżące u podstaw stanowisko HIG to ta sama reguła warstwowania, na której opiera się ten wpis: Liquid Glass należy do chromu, a nie do obszaru treści, ponieważ szklana powierzchnia bez treści przewijającej się pod nią nie ma czego załamywać.153
Kwestia GlassEffectContainer
Apple zaleca GlassEffectContainer, ilekroć aplikacja używa .glassEffect() na wielu widokach, z dwóch powodów: lepszej wydajności renderowania (efekty szkła są przetwarzane wsadowo) oraz możliwości przekształcania (morph) kształtów jeden w drugi podczas przejść.1
Nie użyłem go. Uzasadnienie jest specyficzne dla aplikacji, a nie zaprzeczeniem wskazówek Apple. Return ma dziewięć szklanych widoków, z których żaden nie musi przekształcać się między sobą.46 Selektor czasu trwania nigdy nie animuje się w przycisk start. Tekst timera nigdy nie animuje się w rząd przycisków ustawień. Każdy element szkła jest niezależny. API przekształcania nie miałoby przypadku, na który mogłoby zadziałać, a reguły odstępów kontenera ograniczyłyby układy, które dziś nie wymagają żadnej koordynacji.
Argumentu o wydajności renderowania nie mogę w pełni obalić bez pomiaru. Dokumentacja Apple ostrzega, że „zbyt wiele” efektów szkła poza kontenerem może obniżyć wydajność.1 Dziewięć widoków w Return nigdy nie dzieli ekranu naraz (selektor czasu trwania pojawia się tylko w stanie menu, przycisk stop tylko podczas wstrzymania w trakcie sesji). W dowolnej klatce naliczam trzy lub cztery widoczne elementy szkła, co działało płynnie na każdym urządzeniu, które testowałem w iOS, iPadOS, macOS, watchOS i tvOS, ale nie wykonałem śladu w Instruments porównującego rozwiązanie opakowane kontenerem z samym modyfikatorem. Uczciwe ujęcie: Return pomija GlassEffectContainer na podstawie zaobserwowanego dobrego doświadczenia użytkownika, a nie zmierzonej równoważności wydajności.
Reguła, którą z tego wyciągnąłem: GlassEffectContainer jest dla aplikacji, w których wiele elementów szkła jest widocznych i animowanych jednocześnie. Przykład Apple to renderowanie zestawu symboli z glassEffectUnion(id:namespace:): cztery symbole pogody, które płynnie łączą się i rozdzielają jako jedna jednostka.1 To podręcznikowy przypadek użycia. Jeśli przyszła funkcja Return będzie wymagać, by elementy szkła przekształcały się lub współdzieliły reguły odstępów kontenera, kontener będzie właściwym narzędziem do dodania wtedy. Dla dzisiejszej aplikacji jeszcze nie trafiłem na ten przypadek.
Pułapki, które mnie złapały
Trzy rzeczywiste błędy z produkcji:
Drganie szklanych cyfr. SF Pro Rounded ma cyfry o zmiennej szerokości w renderowaniu proporcjonalnym. W miarę odliczania timera wyświetlany ciąg zmieniał długość, a otaczający HStack przeprojektowywał się co sekundę, drgając całym timerem. Poprawka: komórki o stałej szerokości dla każdego znaku. Każda cyfra otrzymuje cellWidth równe fontSize * 0.6, każdy dwukropek fontSize * 0.3, a HStack staje się stabilną siatką.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)
}
}
Komórki nie są zgodne ze standardem Apple; to obejście dla renderowania o proporcjonalnej szerokości przy małych, stałych rozmiarach czcionki. SF Pro Rounded od Apple z .monospacedDigit() rozwiązałby ten sam problem na Text, ale modyfikator nie jest dostępny w niestandardowym rendererze szkła opartym na Shape. Układ o stałych komórkach jest substytutem.
Nadpisanie kierunku układu w tvOS. Ten sam GlassTimerText działał na iOS, iPadOS, macOS i tvOS. Konkretnie na tvOS HStack był odbijany lustrzanie w środowisku języka pisanego od prawej do lewej, mimo że wersja iOS respektowała nadpisanie wewnątrz środowiska. Poprawka: przypiąć kierunek układu zarówno przez wartość środowiskową, jak i przez jawny modyfikator flipsForRightToLeftLayoutDirection(false), zastosowany bezpośrednio do HStack komórek cyfr (nadrzędny VStack osobno stosuje nadpisanie środowiskowe, aby kopia odbicia je odziedziczyła):6
HStack(spacing: 0) { ... }
.flipsForRightToLeftLayoutDirection(false)
.environment(\.layoutDirection, .leftToRight)
Powód: HStack w tvOS wydaje się ignorować nadpisanie na poziomie środowiska w niektórych wersjach, a flipsForRightToLeftLayoutDirection(false) to jawny kontrakt braku odbicia, który jest respektowany bardziej niezawodnie.12 Pas i szelki.
Redukcja ruchu przy przekształceniu cyfr. Liquid Glass domyślnie animuje przekształcenia (morph) między wyświetlanymi ciągami. Użytkownicy z włączonym accessibilityReduceMotion widzieli przekształcenie jako migotanie. Poprawka:6
.animation(reduceMotion ? nil : .easeInOut(duration: 0.15), value: displayTime)
Modyfikator animacji odczytuje @Environment(\.accessibilityReduceMotion) i całkowicie wyłącza przejście, gdy redukcja ruchu jest włączona. Wytyczne dostępności Apple są jednoznaczne: każda dekoracyjna animacja musi respektować preferencję ruchu użytkownika.7
Kiedy nie używać Liquid Glass
Odmowa jest częścią projektu.
Nie umieszczaj Liquid Glass w warstwie treści. HIG od Apple jest jednoznaczny, a ignorowanie reguły tworzy mylącą hierarchię: użytkownik nie potrafi rozpoznać, co jest interaktywne, a co jest treścią.3 Jeśli efekt szkła dekoruje wiersz listy lub kartę zdjęcia, projekt walczy z platformą.
Nie używaj szkła na płaskim tle. Liquid Glass załamuje to, co jest za nim. Jeśli „to, co jest za nim” to pojedynczy jednolity kolor, załamanie nie ma czego zginać, a rezultat czyta się jako płaski, zabarwiony prostokąt. Albo umieść szkło nad zróżnicowaną treścią (gradient, obraz, film), albo nie używaj szkła wcale. Ekran timera w Return uruchamia jako tło tematyczny obraz okładkowy i zapętlony film przez VideoBackgroundView,4 właśnie po to, by elementy szkła nad nim zawsze miały teksturę do załamania.
Zachowaj ostrożność przy szkle na treści o wysokiej częstotliwości. Renderowanie materiału szkła jest ograniczone przez GPU, a domyślna animacja przekształcenia między zmianami kształtu szkła jest sama w sobie animacją. Timer aktualizujący się raz na sekundę jest w moich testach w porządku; przebieg fali lub wizualizator dźwięku przy 60 Hz jest niesprawdzony i prawdopodobnie walczy z animacją przekształcenia. Nie zmierzyłem górnej granicy; traktuj to jako heurystykę, a nie zmierzony próg. Dokumentacja Apple żadnego nie podaje.
Nie wdrażaj szkła bez przetestowania redukcji ruchu. Każda animacja szkła powinna być uzależniona od accessibilityReduceMotion.7 Domyślne przekształcenie między kształtami szkła to efekt kinetyczny, a nie tylko wygaszenie.
Co Liquid Glass oznacza dla aplikacji wdrażanych na iOS 26+
Teza jest niewielka. Liquid Glass to jednoliniowe API tylko wtedy, gdy aplikacja już respektuje regułę warstwowania HIG. Aplikacja SwiftUI, która umieszcza kontrolki w warstwie funkcjonalnej, a treść w warstwie treści, może przyjąć Liquid Glass za pomocą modyfikatorów .glassEffect() i domyślnie sprawiać wrażenie natywnej.
Aplikacje, które mieszają obie warstwy (kontrolki wewnątrz wierszy listy, paski nawigacji traktowane jako treść, dekoracyjny chrom na kartach zdjęć), przyjmą Liquid Glass i będą sprawiać wrażenie niewłaściwych. Materiał jest poprawny; architektura pod nim nie.
Wzorzec niestandardowego Shape (Wzorzec 1) rozszerza regułę czysto. Wszystko, co funkcjonalnie jest kontrolką, może przyjąć Liquid Glass, nawet jeśli nie wygląda jak „kontrolka” w konwencjonalnym sensie. Timer to kontrolka, miernik poziomu to kontrolka, wskaźnik postępu to kontrolka. Liquid Glass na każdym z nich jest zgodny ze specyfikacją.
Połącz ten wpis z moimi wcześniejszymi tekstami o wdrażaniu warstwy danych tej samej aplikacji przez App Intents oraz przez serwer MCP. Warstwa wizualna to trzecia powierzchnia tego samego stosu: typowane encje dla systemowej AI, format pliku dla agentów międzymodelowych (cross-LLM) oraz Liquid Glass dla człowieka przy urządzeniu.8
FAQ
Czy mogę używać .glassEffect() na platformach innych niż iOS 26?
Modyfikator .glassEffect() jest dostępny w iOS 26+, iPadOS 26+, macOS 26+, watchOS 26+, tvOS 26+, visionOS 26+. Platformy sprzed wersji 26 mają .background(.regularMaterial) i podobne, które tworzą efekty matowego szkła, ale nie nowe załamanie Liquid Glass.1
Czy GlassEffectContainer zmienia wizualizację?
Elementy szkła opakowane kontenerem mogą scalać swoje kształty, gdy ich reguły odstępów powodują nakładanie się. Bez kontenera każdy .glassEffect() jest niezależny. Dla aplikacji, w których elementy szkła powinny płynnie się łączyć podczas animacji, GlassEffectContainer jest właściwym narzędziem. Dla aplikacji, w których każdy element szkła pozostaje odrębny, kontener jest nadmiarem.1
Dlaczego nie używać Text bezpośrednio z .foregroundStyle(.thinMaterial)?
thinMaterial to materiał standardowy, a nie Liquid Glass. Wizualizacja to nakładka matowego szkła, a nie efekt szkła z załamaniem i zaginaniem światła charakterystyczny dla Liquid Glass.3 Dla tekstu, który ma wyglądać konkretnie jak nowy materiał, .glassEffect(.clear, in: customShape) jest wspieraną ścieżką.
Jak zrobić zrzut ekranu Liquid Glass na potrzeby marketingu?
Efekty szkła są renderowane przez GPU w czasie wykonania, więc zrzuty ekranu robi się z symulatora lub urządzenia z już zastosowanym efektem. Oficjalny materiał referencyjny Liquid Glass od Apple pochodzi ze stron dokumentacji HIG oraz sesji WWDC 2025.3
Czy GlassTextShape działa dla dowolnego tekstu, czy tylko dla cyfr?
Działa dowolny ciąg, który Core Text potrafi rozłożyć. Return używa go dla cyfr i dwukropka, ale ten sam Shape działa dla liter, symboli, emoji (z odpowiednią czcionką) lub mieszanych ciągów. Wydajność jest ograniczona liczbą glifów; długi akapit renderowany jako szkło byłby kosztowny, ale sześcioznakowy timer jest trywialny.
Trzy wzorce, jedna reguła i jedno API, które świadomie pominąłem. Liquid Glass to trzecia powierzchnia aplikacji na iOS 26+, znajdująca się na szczycie typowanych encji i współdzielonych formatów plików. Jednoliniowe API jest prawdziwe. To reguła HIG pod nim sprawia, że ten jeden wiersz działa.
Bibliografia
-
Apple Developer, “Applying Liquid Glass to custom views”. Dokumentacja modyfikatora
glassEffect(_:in:),GlassEffectContainer,glassEffectUnion(id:namespace:),glassEffectID(_:in:)orazGlassEffectTransition. Domyślny wariant.regular, domyślny kształtCapsule. ↩↩↩↩↩↩↩↩↩↩ -
Autorska aplikacja Return, timer do medytacji opublikowany w App Store 21 kwietnia 2026, dostępny na iPhone, iPad, Mac, Apple Watch i Apple TV. Używa SwiftUI, SwiftData i HealthKit na iOS 26+ / macOS 26+. ↩
-
Apple Developer, “Materials” Human Interface Guidelines. Definiuje regułę warstwy funkcjonalnej kontra warstwy treści dla Liquid Glass: „Don’t use Liquid Glass in the content layer.” Wymienia warianty regular i clear oraz ich zamierzone zastosowania. ↩↩↩↩↩↩↩↩↩↩↩↩↩
-
Kod produkcyjny w
Return/Return/ContentView.swift(siedem miejsc wywołania.glassEffect()),Return/Return/GlassTimerText.swift(jedno miejsce wywołania naGlassDigitCell) orazReturn/ReturnTV/TVContentView.swift(jedno miejsce wywołania na wskaźniku „Paused” w tvOS). Łącznie dziewięć. PlusReturn/Return/VideoBackgroundView.swift, który renderuje tematyczny obraz okładkowy i zapętlony film, przez które załamują się elementy szkła. ↩↩↩↩ -
Kod produkcyjny w
Return/Return/GlassTextShape.swift. Zgodne zShapeopakowanie wokół Core Text. Utworzone 26 listopada 2025, zawarte w wydanej wersji App Store v1.0. ↩↩ -
Kod produkcyjny w
Return/Return/GlassTimerText.swift. WidokiGlassDigitCell,GlassTimerTextorazGlassTimerDisplay. Implementuje układ komórek o stałej szerokości, odbicie lustrzane oraz uzależnienie od redukcji ruchu. ↩↩↩↩↩↩↩ -
Apple Developer, wartość środowiskowa “accessibilityReduceMotion”. Aplikacje muszą respektować preferencję ruchu użytkownika; domyślne animacje przekształcenia na Liquid Glass powinny być uzależnione od tej wartości. ↩↩↩
-
Analiza autora w App Intents Are Apple’s New API to Your App oraz Two Agent Ecosystems, One Shopping List. Model trzech powierzchni: App Intents dla Apple Intelligence, MCP dla agentów międzymodelowych (cross-LLM), Liquid Glass dla człowieka przy urządzeniu. ↩
-
Apple Developer, “glassEffect(_:in:isEnabled:)” na
View. Parametrin:przyjmuje dowolny typ zgodny zShape. Domyślny kształt toCapsule. ↩ -
Apple Developer, protokół “Shape”.
Shapeto dowolny typ, który produkujePathdla danego prostokąta. Niestandardowe kształty mogą opakowywać dowolne daneCGPath. ↩ -
Apple Developer, “Core Text Programming Guide” oraz
CTLineCreateWithAttributedString. Core Text to silnik tekstowy niższego poziomu używany do rozkładania atrybutowanych ciągów na przebiegi glifów i wyciągania ścieżek poszczególnych glifów. ↩ -
Apple Developer, “flipsForRightToLeftLayoutDirection(_:)”. Jawnie nadpisuje odbicie lustrzane RTL na
Viewniezależnie od otaczającej wartości środowiskowej\.layoutDirection. ↩ -
Apple, “WWDC 2025 Highlights” via Apple Newsroom. Liquid Glass ogłoszony jako jednolity materiał projektowy w iOS 26, iPadOS 26, macOS 26, watchOS 26, tvOS 26 i visionOS 26. Sesje: “Meet Liquid Glass” (WWDC 2025), “Build a SwiftUI app with Liquid Glass”. ↩
-
Apple Developer, “LinearGradient”, “scaleEffect(x:y:anchor:)”, “mask(_:)”. Standardowe prymitywy SwiftUI, wszystkie dostępne od iOS 13. ↩
-
Apple, WWDC 2026 SwiftUI Group Lab (sesja 2). Sparafrazowane z lokalnie transkrybowanego nagrania WWDC 2026 SwiftUI Group Lab (sesja 2); Apple nie publikuje oficjalnych napisów do laboratoriów. Źródło dla ukrywania współdzielonego szklanego tła elementu paska narzędzi w celu pokazania nieszklanej treści (zdjęcia profilowego), nowszego API, które usuwa jedynie margines treści przycisku paska narzędzi zamiast tła i marginesu razem, preferencji dla wyróżnionego stylu szklanego przycisku oraz
buttonBorderShapezamiast.glassEffectna przycisku, a także uzasadnienia warstwowania chrom-nie-treść. Wspierające symbole są udokumentowane wsharedBackgroundVisibility(_:)naCustomizableToolbarContent, który przyjmuje wartośćVisibilitytaką jak.hidden, orazbuttonBorderShape(_:);glassProminentto wyróżnionyPrimitiveButtonStyleLiquid Glass. Konkretnego API marginesu treści nazwanego w laboratorium nie udało się potwierdzić względem opublikowanej dokumentacji Apple, więc jest opisane przez zachowanie, a nie potwierdzone symbolem. ↩↩