Úvod: Prečo Liquid Glass mení pravidlá hry v iOS 26
Ak sledujete svet Apple vývoja, určite ste to zaregistrovali — iOS 26 priniesol najväčšiu vizuálnu zmenu od čias iOS 7. Volá sa Liquid Glass a nie je to len kozmetická úprava. Je to kompletne nový dizajnový jazyk, ktorý mení spôsob, akým používatelia vnímajú a interagujú s aplikáciami.
Priesvitný, dynamický materiál. Odráža svetlo, láme farby okolia a reaguje na dotyk v reálnom čase. Keď som to prvýkrát videl na WWDC, úprimne — chvíľu mi trvalo, kým som pochopil rozsah tej zmeny.
Tak čo to znamená pre vás ako vývojára? Systémové komponenty — navigačné lišty, tab bary, toolbary — automaticky získajú nový vzhľad po jednoduchej rekompilácii s iOS 26 SDK. Ale ak chcete Liquid Glass aplikovať na vlastné views, vytvárať morphing animácie alebo riešiť hybridné UIKit + SwiftUI architektúry, potrebujete rozumieť novým API. A presne o tom si dnes povieme.
Čo je Liquid Glass a ako vlastne funguje
Liquid Glass nie je jednoduchý blur efekt. Je to dynamický materiál prvej triedy, ktorý kombinuje optické vlastnosti skla s fluiditou kvapaliny. V praxi to prináša niekoľko kľúčových vlastností:
- Lom svetla v reálnom čase — materiál láme obsah za ním, podobne ako skutočné sklo
- Spekulárne odlesky — reagujú na pohyb zariadenia a orientáciu
- Adaptívne tiene — dynamicky sa prispôsobujú pozadiu
- Interaktívne správanie — materiál reaguje na dotyk a pointer interakcie
Filozofia je jasná: Liquid Glass patrí na navigačnú vrstvu, ktorá sa vznáša nad obsahom aplikácie. Nikdy ho neaplikujte priamo na obsah — zoznamy, tabuľky, médiá. Obsah zostáva primárny, sklené kontrolky poskytujú funkčný overlay.
Toto je dôležité si zapamätať, pretože veľa vývojárov (vrátane mňa na začiatku) má tendenciu dať sklo na všetko, čo vidí.
Základné použitie: Modifikátor .glassEffect()
Apple v iOS 26 dodal trojicu hlavných SwiftUI API: glassEffect, GlassEffectContainer a glassEffectID. Poďme na to od začiatku.
Prvý sklený view za 3 riadky kódu
Pridanie Liquid Glass na vlastný view je prekvapivo jednoduché:
import SwiftUI
struct BasicGlassView: View {
var body: some View {
Text("Ahoj, Liquid Glass!")
.padding()
.glassEffect()
}
}
To je celé. Modifikátor .glassEffect() bez parametrov aplikuje predvolený variant .regular v tvare kapsuly. SwiftUI automaticky použije vibrantnú farbu textu, ktorá sa adaptuje na pozadie a zachováva čitateľnosť.
Signatúra API
Pre tých z vás, ktorí chcú vedieť presne, s čím pracujú — kompletná signatúra vyzerá takto:
func glassEffect<S: Shape>(
_ glass: Glass = .regular,
in shape: S = DefaultGlassEffectShape,
isEnabled: Bool = true
) -> some View
Tri varianty Glass
Glass.regular— predvolený adaptívny variant pre väčšinu UI prvkovGlass.clear— vysoká priehľadnosť, ideálny pre pozadia bohaté na médiáGlass.identity— žiadny vizuálny efekt, užitočný na podmienené vypnutie
Ten posledný (.identity) sa vám bude hodiť častejšie, než by ste čakali — napríklad pri podmienenom zapínaní efektu podľa stavu alebo nastavení prístupnosti.
Vlastné tvary a tintovanie
Prispôsobenie tvaru
Predvolený tvar kapsuly nemusí vyhovovať každému dizajnu. Našťastie SwiftUI vám umožňuje špecifikovať akýkoľvek tvar:
Text("Zaoblený obdĺžnik")
.font(.title2)
.padding()
.glassEffect(in: .rect(cornerRadius: 16.0))
// Kruhový sklený efekt
Image(systemName: "star.fill")
.font(.title)
.frame(width: 60, height: 60)
.glassEffect(in: .circle)
Tintovanie skla
Pre zvýraznenie dôležitých prvkov môžete použiť tintovanie. Ale pozor — používajte ho uvážlivo. Iba na vyjadrenie významu, nie len pre vizuálny efekt:
// Tintované sklo
Text("Dôležitá akcia")
.padding()
.glassEffect(.regular.tint(.blue))
// S upravenou opacitou
Text("Jemný tint")
.padding()
.glassEffect(.regular.tint(.purple.opacity(0.6)))
Z vlastnej skúsenosti — modrý a fialový tint vyzerajú najlepšie. Červená a zelená môžu byť trochu „krikľavé", pokiaľ ich nepoužívate na vyjadrenie stavu (chyba/úspech).
Interaktívne sklené efekty
Pre vlastné ovládacie prvky a kontajnery s interaktívnymi elementmi je tu modifikátor .interactive(). Zabezpečí, že sklený efekt bude vizuálne reagovať na dotyky — a to robí UI naozaj živým:
Image(systemName: "heart.fill")
.font(.title2)
.frame(width: 60, height: 60)
.glassEffect(.regular.interactive())
Vstavané sklené štýly tlačidiel
SwiftUI poskytuje dva hotové štýly tlačidiel, takže nemusíte nič vymýšľať:
VStack(spacing: 16) {
// Priesvitné sklo — sekundárne akcie
Button("Zrušiť") { }
.buttonStyle(.glass)
// Výrazné sklo — primárne akcie
Button("Potvrdiť") { }
.buttonStyle(.glassProminent)
}
Štýl .glass je určený pre sekundárne akcie, zatiaľ čo .glassProminent s vyššou opacitou je pre primárne akcie. Jednoduché a funkčné.
GlassEffectContainer: Zoskupovanie a morphing
GlassEffectContainer je kontajnerový view, ktorý kombinuje viaceré sklené tvary do jedného materiálu. A toto je podľa mňa najzaujímavejšia časť celého Liquid Glass API.
Dôvody sú dva: výkon (viaceré sklené efekty sa renderujú v jednom CALayer) a morphing animácie.
Základný príklad zoskupenia
GlassEffectContainer(spacing: 40.0) {
HStack(spacing: 20) {
Image(systemName: "pencil")
.frame(width: 44, height: 44)
.glassEffect(.regular.interactive())
Image(systemName: "eraser")
.frame(width: 44, height: 44)
.glassEffect(.regular.interactive())
Image(systemName: "scissors")
.frame(width: 44, height: 44)
.glassEffect(.regular.interactive())
}
}
Parameter spacing určuje, ako blízko musia byť prvky, aby sa vizuálne zlúčili a morfovali do jedného skleného tvaru. Prvky v tejto vzdialenosti sa automaticky spoja do jednej sklenej plochy. Je to trochu magické, keď to vidíte prvýkrát.
Morphing animácie s glassEffectID
Jednou z najefektnejších funkcií Liquid Glass sú plynulé morphing prechody medzi sklenými elementmi. Dosiahnete ich pomocou glassEffectID v kombinácii s @Namespace:
struct ExpandableToolbar: View {
@State private var isExpanded = false
@Namespace private var namespace
var body: some View {
GlassEffectContainer(spacing: 40.0) {
HStack(spacing: 40.0) {
Image(systemName: "scribble.variable")
.font(.title2)
.frame(width: 80, height: 80)
.glassEffect()
.glassEffectID("pencil", in: namespace)
if isExpanded {
Image(systemName: "eraser.fill")
.font(.title2)
.frame(width: 80, height: 80)
.glassEffect()
.glassEffectID("eraser", in: namespace)
Image(systemName: "paintbrush.fill")
.font(.title2)
.frame(width: 80, height: 80)
.glassEffect()
.glassEffectID("brush", in: namespace)
}
}
}
Button(isExpanded ? "Zbaliť" : "Rozšíriť") {
withAnimation(.spring(duration: 0.4)) {
isExpanded.toggle()
}
}
.buttonStyle(.glass)
}
}
SwiftUI využíva identifikátory a spacing kontajnera na určenie, ktoré tvary sa majú morfovať. Keď view s daným ID zmizne alebo sa objaví, systém automaticky animuje prechod medzi tvarmi.
Kedy nastavovať glassEffectID
Dôležitá poznámka: nemusíte nastavovať glassEffectID na každý view. Nastavenie ID na všetky views alebo na žiadny z nich vedie k rovnakému efektu. ID sú užitočné iba vtedy, keď chcete explicitne riadiť, ktoré konkrétne prvky sa majú morfovať medzi sebou.
Takže — nepridávajte ho všade „pre istotu". Používajte ho cielene.
Integrácia s UIKit v hybridných aplikáciách
Mnoho existujúcich projektov (povedzme si úprimne — väčšina väčších komerčných appiek) používa hybridnú architektúru UIKit + SwiftUI. Pre UIKit Apple poskytuje triedy UIGlassEffect a UIVisualEffectView:
import UIKit
let glassEffect = UIGlassEffect(
glass: .regular,
isInteractive: true
)
let effectView = UIVisualEffectView(effect: glassEffect)
effectView.frame = CGRect(x: 0, y: 0, width: 200, height: 50)
effectView.layer.cornerRadius = 12
effectView.clipsToBounds = true
view.addSubview(effectView)
Systémové komponenty v UIKit — UINavigationBar, UITabBar, UIToolbar — získajú Liquid Glass automaticky po rekompilácii s iOS 26 SDK. Bez jediného riadku kódu navyše.
Problémy nastávajú až pri vlastných komponentoch, ktoré mali custom pozadia, tene alebo opacity. Tieto customizácie budete musieť odstrániť alebo prispôsobiť — a tu si pripravte trochu trpezlivosti, lebo nie vždy je jasné, čo presne treba zmeniť.
Spätná kompatibilita s iOS 18
Ak vaša aplikácia podporuje aj staršie verzie iOS (čo je v roku 2026 ešte stále bežné), potrebujete fallback riešenie. Tu je jednoduchý kompatibilný modifikátor:
import SwiftUI
extension View {
@ViewBuilder
func adaptiveGlassEffect() -> some View {
if #available(iOS 26, *) {
self.glassEffect()
} else {
self
.background(.ultraThinMaterial)
.clipShape(Capsule())
.overlay(
Capsule()
.stroke(Color.white.opacity(0.2), lineWidth: 0.5)
)
}
}
}
Pre iOS 18 a staršie sa .ultraThinMaterial s jemným okrajom vizuálne najviac blíži efektu Liquid Glass — aj keď samozrejme postrádá dynamické lomenie svetla a morphing. Ale je to solídny fallback, s ktorým vaša appka nebude vyzerať rozbitá.
Best practices a časté chyby
Kde Liquid Glass používať
- Navigačné lišty a toolbary
- Tab bary a spodné panely
- Plávajúce akčné tlačidlá (FAB)
- Sheety, popovery a kontextové menu
- Systémové alerty a dialógy
Kde Liquid Glass nepoužívať
- Obsahové vrstvy — zoznamy, tabuľky, galérie
- Celoobrazovkové pozadia
- Scrollovateľný obsah
- Vrstvenie viacerých skiel na seba
Najčastejšie chyby
1. Pridávanie .blur alebo .opacity na sklený view — tieto modifikátory interferujú s dynamickými efektmi Liquid Glass. Jednoducho sa im vyhnite.
2. Solídne pozadia za sklom — nepridávajte Color.white alebo Color.black za view s .glassEffect(). Sklo potrebuje priesvitný obsah na správne fungovanie. Toto je asi najčastejšia chyba, ktorú vidím.
3. Príliš veľa skla — aplikovanie .glassEffect() na každý riadok v zozname vytvára vizuálny chaos a každá sklenená vrstva pridáva výpočtovú záťaž. Menej je viac.
4. Staré customizácie navigácie — ak máte custom navigačné tlačidlá s vlastnými pozadiami a paddingom, v iOS 26 budú vyzerať zle. Tieto customizácie treba odstrániť alebo prepracovať.
5. Animačné glitche s Menu — pri použití .glassEffect() na SwiftUI Menu sa objavujú známe animačné chyby. Riešením je vytvorenie vlastného ButtonStyle s aplikovaným glassEffect na label. Nie je to ideálne, ale funguje to.
Prístupnosť a Liquid Glass
Liquid Glass nie je fixný vzhľad — používatelia si ho môžu upraviť alebo úplne vypnúť. A to je niečo, čo nesmieme ignorovať.
struct AccessibleGlassView: View {
@Environment(\.accessibilityReduceTransparency)
var reduceTransparency
@Environment(\.accessibilityReduceMotion)
var reduceMotion
var body: some View {
Text("Prístupné sklo")
.padding()
.glassEffect(
reduceTransparency ? .identity : .regular
)
.animation(
reduceMotion ? .none : .spring(),
value: reduceTransparency
)
}
}
V nastaveniach iOS 26 majú používatelia k dispozícii Reduce Transparency (potlačí väčšinu sklených efektov), Increase Contrast a Reduce Motion (eliminuje lensing efekty). Od iOS 26.1 pribudla aj voľba Tinted, ktorá zvyšuje opacitu skla a zlepšuje kontrast, zatiaľ čo Clear zachováva štandardný vzhľad.
Najlepšia prax? Nechajte systém spracovať prístupnosť automaticky a zasahujte iba vtedy, keď máte špecifický dôvod na override.
Kompletný príklad: Sklená karta profilu
Na záver si ukážeme komplexnejší príklad, ktorý spája všetko, čo sme si prešli, do jedného realistického UI komponentu:
struct GlassProfileCard: View {
let name: String
let role: String
@State private var showActions = false
@Namespace private var cardNamespace
var body: some View {
ZStack {
// Pozadie s gradientom
LinearGradient(
colors: [.blue, .purple, .pink],
startPoint: .topLeading,
endPoint: .bottomTrailing
)
.ignoresSafeArea()
VStack(spacing: 24) {
GlassEffectContainer(spacing: 30) {
VStack(spacing: 16) {
// Avatar
Image(systemName: "person.crop.circle.fill")
.font(.system(size: 60))
.foregroundStyle(.white)
.frame(width: 100, height: 100)
.glassEffect(in: .circle)
.glassEffectID("avatar", in: cardNamespace)
// Info karta
VStack(spacing: 8) {
Text(name)
.font(.title2.bold())
Text(role)
.font(.subheadline)
.foregroundStyle(.secondary)
}
.padding(.horizontal, 32)
.padding(.vertical, 16)
.glassEffect(in: .rect(cornerRadius: 20))
.glassEffectID("info", in: cardNamespace)
// Akčné tlačidlá
if showActions {
HStack(spacing: 16) {
ActionButton(
icon: "message.fill",
label: "Správa"
)
ActionButton(
icon: "phone.fill",
label: "Volať"
)
ActionButton(
icon: "video.fill",
label: "Video"
)
}
.glassEffectID("actions", in: cardNamespace)
}
}
}
Button(showActions ? "Skryť akcie" : "Zobraziť akcie") {
withAnimation(.spring(duration: 0.5)) {
showActions.toggle()
}
}
.buttonStyle(.glassProminent)
}
}
}
}
struct ActionButton: View {
let icon: String
let label: String
var body: some View {
VStack(spacing: 4) {
Image(systemName: icon)
.font(.title3)
Text(label)
.font(.caption)
}
.frame(width: 70, height: 70)
.glassEffect(.regular.interactive())
}
}
Tento príklad demonštruje použitie GlassEffectContainer pre zoskupenie, glassEffectID pre morphing prechody, interaktívne sklené tlačidlá, rôzne tvary skla a animovaný prechod medzi stavmi. Skúste si ho spustiť na simulátore — výsledok stojí za to.
Často kladené otázky
Musím prepísať celú aplikáciu, aby podporovala Liquid Glass?
Nie, vôbec. Systémové komponenty (UINavigationBar, UITabBar, UIToolbar v UIKit aj ich SwiftUI ekvivalenty) automaticky získajú Liquid Glass vzhľad po rekompilácii s iOS 26 SDK. Kód meniť nemusíte. Vlastné komponenty vyžadujú manuálne pridanie modifikátora .glassEffect().
Ako Liquid Glass funguje v tmavom režime?
Liquid Glass sa automaticky adaptuje na obsah za ním. Nad tmavým pozadím sa sklo stáva svetlejším a nad svetlým pozadím tmavším. V tmavom režime funguje rovnako dobre, ale niektorí vývojári hlásili problémy s tmavým/šedým renderovaním na fyzických zariadeniach — uistite sa, že nemáte solídne pozadia za sklenými views.
Aký je vplyv Liquid Glass na výkon a batériu?
Každá sklenená vrstva pridáva výpočtovú záťaž. Používajte GlassEffectContainer na zoskupenie viacerých skiel do jedného CALayer. Implementujte Equatable na views so sklenými efektmi. V režime nízkej spotreby alebo pri aktívnych nastaveniach prístupnosti zvážte použitie .identity variantu.
Môžem použiť Liquid Glass na watchOS alebo visionOS?
Áno. Liquid Glass je jednotný dizajnový jazyk naprieč iOS 26, iPadOS 26, macOS Tahoe, watchOS 26, tvOS 26 aj visionOS 26. API sú identické, ale vizuálne správanie sa môže mierne líšiť podľa platformy.
Ako riešiť spätnú kompatibilitu pre iOS 18?
Použite dostupnostné kontroly s #available(iOS 26, *) a pre staršie verzie implementujte fallback pomocou .ultraThinMaterial s jemným okrajom. Vytvorte si vlastný @ViewBuilder extension, ktorý automaticky vyberie správny variant podľa verzie systému — ukázali sme si to vyššie v sekcii o spätnej kompatibilite.