Inleiding: Een Nieuwe Designtaal voor Apple
Als je de laatste jaren iOS-apps hebt gebouwd, dan weet je dat het visuele ontwerp van het platform best stabiel was. Sinds iOS 7 in 2013 flat design introduceerde, zijn de ontwerpprincipes eigenlijk nooit écht drastisch veranderd. Ja, er kwamen nieuwe features bij — Dark Mode, widgets, Dynamic Island — maar de kern? Die bleef gewoon herkenbaar.
Tot iOS 26.
Op WWDC 2025 onthulde Apple Liquid Glass: de meest ingrijpende visuele vernieuwing in meer dan tien jaar. En eerlijk gezegd, als SwiftUI-ontwikkelaar krijg je er verrassend veel gratis bij. Maar om het écht goed in te zetten — en niet alleen de standaardinstellingen te gebruiken — moet je de nieuwe API's en ontwerpprincipes begrijpen.
In deze gids lopen we door alles wat je moet weten over Liquid Glass in SwiftUI. Van de basis van de .glassEffect()-modifier tot geavanceerde morph-transities met GlassEffectContainer, van toolbar-aanpassingen tot toegankelijkheid. Met praktische codevoorbeelden die je direct kunt gebruiken in je eigen projecten.
Wat Is Liquid Glass?
Liquid Glass is een nieuw adaptief materiaal dat Apple heeft ontwikkeld voor besturingselementen en navigatie. Het combineert de optische eigenschappen van glas — lichtbreking, reflectie, transparantie — met de vloeiendheid van vloeistof. Het resultaat is een lichtgewicht, dynamisch materiaal dat echt leeft op je scherm.
De belangrijkste visuele kenmerken:
- Real-time lichtbreking (lensing): Het materiaal buigt het licht van de achterliggende content, waardoor een subtiel vergrotingseffect ontstaat.
- Speculaire highlights: Lichtreflecties die dynamisch reageren op de beweging van het apparaat en de positie van de gebruiker.
- Adaptieve schaduwen: Schaduwen die zich automatisch aanpassen aan de achtergrondcontent en lichtomstandigheden.
- Interactief gedrag: Het materiaal reageert op aanrakingen met subtiele animaties.
Het kernprincipe achter Liquid Glass is gelaagdheid: content zit op de onderste laag, terwijl navigatie-elementen als glazen oppervlakken erboven zweven. Dit creëert een duidelijke visuele hiërarchie die de aandacht op de content richt.
Liquid Glass is beschikbaar op alle Apple-platforms: iOS 26, iPadOS 26, macOS Tahoe, watchOS 26, tvOS 26 en visionOS 26. Overigens is het geïnspireerd door de interface van de Vision Pro — Apple brengt hiermee een uniforme designtaal naar al hun apparaten.
Automatische Adoptie: Wat Je Gratis Krijgt
Goed nieuws. Als je je app opnieuw compileert met Xcode 26, krijg je automatisch het Liquid Glass-uiterlijk voor veel standaard UI-elementen. Letterlijk niets voor doen.
Deze elementen krijgen automatisch een Liquid Glass-behandeling:
- NavigationBar — De navigatiebalk wordt transparant met een glazen achtergrond
- TabBar — Tab-balken krijgen het nieuwe glazen uiterlijk en kunnen inkrimpen bij scrollen
- Toolbars — Toolbar-items worden op een glazen oppervlak geplaatst
- Sheets — Gedeeltelijke sheets zweven nu boven de interface met afgeronde hoeken
- Popovers en Menu's — Krijgen automatisch het glazen materiaal
- Alerts — Meldingen gebruiken het nieuwe materiaal
- Zoekbalken — De zoekinterface past zich aan
- Toggles, Sliders en Pickers — Transformeren naar Liquid Glass tijdens interactie
Dat gezegd hebbende: je wilt waarschijnlijk wél controleren hoe je voorgrond-elementen contrasteren met de dynamische achtergrond. Omdat Liquid Glass transparant is, kan de leesbaarheid van tekst en iconen veranderen afhankelijk van wat erachter zit. Dat is iets om in de gaten te houden.
De .glassEffect() Modifier: De Basis
De kern van het Liquid Glass-systeem in SwiftUI is de .glassEffect()-modifier. Hiermee pas je het glazen materiaal toe op elke SwiftUI-view.
De eenvoudigste vorm
In zijn meest basale vorm voeg je simpelweg .glassEffect() toe aan een view:
import SwiftUI
struct GlasKnopView: View {
var body: some View {
Button("Tik hier") {
print("Knop ingedrukt!")
}
.padding(.horizontal, 24)
.padding(.vertical, 12)
.glassEffect()
}
}
Standaard gebruikt .glassEffect() de .regular-stijl met een .capsule-vorm. De volledige signatuur ziet er zo uit:
.glassEffect(
_ glass: Glass = .regular,
in shape: some Shape = .capsule,
isEnabled: Bool = true
) -> some View
Je kunt dus de stijl, vorm en of het effect actief is allemaal configureren. Lekker flexibel.
Glass-stijlen: Regular, Clear en Identity
Het Glass-type biedt drie statische varianten die bepalen hoe het glazen materiaal eruitziet.
.regular — De standaard
Glass.regular is de standaardvariant en biedt een gebalanceerde mix van transparantie, vervaging en lichtbreking. Dit is wat je in de meeste gevallen wilt gebruiken:
Text("Regulier glas")
.padding()
.glassEffect(.regular)
.clear — Hoge transparantie
Glass.clear biedt een hogere mate van transparantie met minimale vervaging. Handig voor elementen die minder visuele nadruk nodig hebben:
Text("Helder glas")
.padding()
.glassEffect(.clear)
.identity — Geen effect
Glass.identity schakelt het glaseffect effectief uit. Dit is vooral handig in combinatie met conditionele logica — denk bijvoorbeeld aan toegankelijkheid:
@Environment(\.accessibilityReduceTransparency) var verminderdTransparantie
var body: some View {
Text("Adaptief glas")
.padding()
.glassEffect(verminderdTransparantie ? .identity : .regular)
}
Let op: Meng .regular en .clear niet binnen dezelfde groep besturingselementen. Dat creëert een verwarrende visuele hiërarchie. Kies één stijl per controlegroep.
Tinten en Interactiviteit
Glass-effecten kun je aanvullen met kleur en interactief gedrag. Dat maakt de gebruikerservaring een stuk rijker.
Kleurtinten toevoegen
Met de .tint()-methode op een Glass-instantie voeg je een subtiele kleurlaag toe aan het glaseffect:
// Blauwe tint voor een primaire actie
Button("Opslaan") { bewaarDocument() }
.padding()
.glassEffect(.regular.tint(.blue))
// Paarse tint met aangepaste dekking
Button("Delen") { deelDocument() }
.padding()
.glassEffect(.regular.tint(.purple.opacity(0.6)))
Een belangrijke richtlijn van Apple hier: gebruik tinten alleen om semantische betekenis over te brengen. Blauw voor een primaire actie, rood voor een destructieve — dat zijn goede toepassingen. Tinten puur voor de sier? Dat voegt visuele ruis toe en is af te raden.
Interactiviteit inschakelen
Met .interactive() reageert het glaseffect op aanrakingen met subtiele animaties:
Button("Interactieve knop") {
voerActieUit()
}
.padding()
.glassEffect(.regular.interactive())
// Combineer tint en interactiviteit — de volgorde maakt niet uit
Button("Primaire actie") {
voerPrimaireActieUit()
}
.padding()
.glassEffect(.regular.tint(.blue).interactive())
Schakel interactiviteit alleen in op aantikbare elementen. Op passieve content zoals labels voegt het onnodige renderingkosten toe zonder dat de gebruiker er iets aan heeft.
Aangepaste Vormen
De .glassEffect()-modifier accepteert elke SwiftUI Shape als parameter. Dat geeft je volledige controle over de visuele begrenzing van het glasoppervlak.
// Capsule — de standaard
Text("Capsule")
.padding()
.glassEffect(.regular, in: .capsule)
// Cirkel
Image(systemName: "star.fill")
.font(.title)
.frame(width: 60, height: 60)
.glassEffect(.regular, in: .circle)
// Afgeronde rechthoek
VStack {
Text("Kaartweergave")
Text("Met glaseffect")
.font(.caption)
}
.padding()
.glassEffect(.regular, in: RoundedRectangle(cornerRadius: 16))
// Container-concentrische hoeken
Text("Concentrisch")
.padding()
.glassEffect(.regular, in: .rect(cornerRadius: .containerConcentric))
Die .containerConcentric-optie is trouwens bijzonder handig: het past de hoekradius automatisch aan zodat deze visueel mooi samenvalt met de container eromheen. Perfect voor geneste elementen.
Eigen vormen definiëren
Je kunt ook volledig aangepaste vormen gebruiken. Alles dat voldoet aan het Shape-protocol werkt gewoon:
struct DiamantVorm: Shape {
func path(in rect: CGRect) -> Path {
var pad = Path()
pad.move(to: CGPoint(x: rect.midX, y: rect.minY))
pad.addLine(to: CGPoint(x: rect.maxX, y: rect.midY))
pad.addLine(to: CGPoint(x: rect.midX, y: rect.maxY))
pad.addLine(to: CGPoint(x: rect.minX, y: rect.midY))
pad.closeSubpath()
return pad
}
}
// Gebruik de aangepaste vorm
Image(systemName: "diamond.fill")
.font(.largeTitle)
.frame(width: 80, height: 80)
.glassEffect(.regular, in: DiamantVorm())
GlassEffectContainer: Groeperen en Morphen
Oké, hier wordt het echt interessant. Een van de krachtigste features van het Liquid Glass-systeem is de GlassEffectContainer. Deze container combineert meerdere glasvormen tot één samenhangende glasvorm die kan morphen en blenden.
Basisgebruik
Wanneer je views met .glassEffect() in een GlassEffectContainer plaatst, gebeuren er automatisch een paar dingen:
- Overlappende glasvormen worden visueel samengevoegd
- Consistente vervagings- en lichteffecten worden toegepast
- Vloeiende morph-transities worden mogelijk
- De rendering-prestaties verbeteren
struct GlasToolbarView: View {
var body: some View {
ZStack {
// Achtergrondafbeelding
Image("landschap")
.resizable()
.ignoresSafeArea()
// Glascontainer met knoppen
GlassEffectContainer {
HStack(spacing: 16) {
Button {
// Actie
} label: {
Image(systemName: "house.fill")
}
.glassEffect()
Button {
// Actie
} label: {
Image(systemName: "gear")
}
.glassEffect()
Button {
// Actie
} label: {
Image(systemName: "person.fill")
}
.glassEffect()
}
.padding()
}
}
}
}
De spacing-parameter
De GlassEffectContainer accepteert een optionele spacing-parameter die bepaalt hoe dicht elementen bij elkaar moeten zijn voordat ze visueel samensmelten:
// Elementen binnen 40 punten smelten samen
GlassEffectContainer(spacing: 40.0) {
HStack(spacing: 20) {
ForEach(iconen, id: \.self) { icoon in
Image(systemName: icoon)
.font(.title2)
.frame(width: 44, height: 44)
.glassEffect()
}
}
}
Een hogere spacing-waarde betekent dat elementen eerder samensmelten. Speel hier gerust mee om het juiste visuele effect te vinden voor jouw situatie.
Morph-transities met glassEffectID
Het échte magie van GlassEffectContainer komt naar voren bij morph-transities. Met .glassEffectID() koppel je gerelateerde glaselementen aan elkaar, zodat ze vloeiend kunnen transformeren tussen staten.
Een uitklapbaar actiemenu bouwen
Dit is een populair UI-patroon dat je vast al kent: een floating action button die uitklapt naar meerdere opties. Met Liquid Glass ziet het er fantastisch uit:
struct UitklapbaarActieMenu: View {
@State private var isUitgeklapt = false
@Namespace private var namespace
let acties: [(naam: String, icoon: String, kleur: Color)] = [
("Camera", "camera.fill", .blue),
("Foto", "photo.fill", .green),
("Document", "doc.fill", .orange)
]
var body: some View {
VStack {
Spacer()
GlassEffectContainer(spacing: 20) {
VStack(spacing: 12) {
if isUitgeklapt {
ForEach(acties, id: \.naam) { actie in
Button {
// Voer actie uit
} label: {
Image(systemName: actie.icoon)
.font(.title2)
.frame(width: 50, height: 50)
}
.glassEffect(
.regular.tint(actie.kleur),
in: .circle
)
.glassEffectID(actie.naam, in: namespace)
}
}
Button {
withAnimation(.bouncy(duration: 0.4)) {
isUitgeklapt.toggle()
}
} label: {
Image(systemName: isUitgeklapt
? "xmark" : "plus")
.font(.title)
.frame(width: 60, height: 60)
}
.glassEffect(.regular.interactive(), in: .circle)
.glassEffectID("hoofdknop", in: namespace)
}
}
.padding(.bottom, 30)
}
}
}
De stappen voor een morph-transitie zijn eigenlijk best overzichtelijk:
- Plaats alle deelnemende views in dezelfde
GlassEffectContainer - Gebruik
.glassEffectID()met een gemeenschappelijke@Namespaceop elke view - Toon views conditioneel met een animatie
Het resultaat? Een vloeiende, natuurlijke transitie waarbij de glasvormen in elkaar overlopen. Precies het soort polish dat een goede app onderscheidt van een geweldige.
Toolbars in het Liquid Glass-tijdperk
Toolbars hebben een flinke visuele update gekregen in iOS 26. Toolbar-items worden nu op een glazen oppervlak geplaatst dat boven je content zweeft en zich automatisch aanpast aan wat eronder zit.
De nieuwe ToolbarSpacer
Een van de handige nieuwe toevoegingen is ToolbarSpacer. Hiermee kun je toolbar-items groeperen en scheiden op een manier die voorheen nogal omslachtig was:
struct DocumentEditorView: View {
var body: some View {
NavigationStack {
TextEditor(text: .constant("Documentinhoud..."))
.toolbar {
ToolbarItemGroup(placement: .bottomBar) {
Button {
// Vet
} label: {
Image(systemName: "bold")
}
Button {
// Cursief
} label: {
Image(systemName: "italic")
}
// Vaste ruimte tussen groepen
ToolbarSpacer(.fixed, spacing: 20)
Button {
// Links uitlijnen
} label: {
Image(systemName: "text.alignleft")
}
Button {
// Centreren
} label: {
Image(systemName: "text.aligncenter")
}
// Flexibele ruimte duwt naar rechts
ToolbarSpacer(.flexible)
Button {
// Delen
} label: {
Image(systemName: "square.and.arrow.up")
}
}
}
}
}
}
ToolbarSpacer(.fixed, spacing:) creëert een vaste ruimte tussen items, terwijl ToolbarSpacer(.flexible) zich uitbreidt om beschikbare ruimte op te vullen. Simpel, maar effectief voor het maken van visueel duidelijke groepen.
Toolbar-plaatsing en glasstijlen
In het Liquid Glass-systeem bepaalt ToolbarItemPlacement niet alleen de positie, maar ook het visuele uiterlijk van items. Zo past .confirmationAction automatisch de prominente glasstijl toe:
NavigationStack {
VStack {
// Content
}
.toolbar {
ToolbarItem(placement: .cancellationAction) {
Button("Annuleer") { }
// Krijgt automatisch een subtiele glasstijl
}
ToolbarItem(placement: .confirmationAction) {
Button("Bewaar") { }
// Krijgt automatisch de prominente glasstijl
}
}
}
Apple raadt aan om symbool-gebaseerde knoppen te gebruiken in toolbars, met zowel een afbeelding als een tekstlabel. Het nieuwe ontwerpsysteem geeft duidelijk de voorkeur aan iconen:
Button {
deelInhoud()
} label: {
Label("Delen", systemImage: "square.and.arrow.up")
}
Tab Bars: Inkrimpen, Accessories en Meer
De tab bar heeft eerlijk gezegd een van de meest opvallende updates gekregen. In iOS 26 krimpt de tab bar automatisch in wanneer gebruikers scrollen, waardoor meer ruimte vrijkomt voor content. Dat voelt verrassend natuurlijk aan.
Minimaliseergedrag instellen
Met de nieuwe .tabBarMinimizeBehavior()-modifier bepaal je wanneer de tab bar inkrimpt:
TabView {
Tab("Home", systemImage: "house.fill") {
HomeView()
}
Tab("Zoeken", systemImage: "magnifyingglass") {
ZoekView()
}
Tab("Profiel", systemImage: "person.fill") {
ProfielView()
}
}
.tabBarMinimizeBehavior(.onScrollDown) // Krimpt in bij scrollen
// Andere opties:
// .tabBarMinimizeBehavior(.automatic) // Systeem bepaalt
// .tabBarMinimizeBehavior(.never) // Nooit inkrimpen
Bottom Accessory
Een leuke toevoeging in iOS 26 is de bottom accessory — een klein bedieningselement dat onder de tab bar zweeft. Perfect voor mediabediening, voortgangsindicatoren of snelle acties:
TabView {
Tab("Muziek", systemImage: "music.note") {
MuziekBibliotheekView()
}
Tab("Zoeken", systemImage: "magnifyingglass") {
ZoekView()
}
}
.tabViewBottomAccessory {
HStack {
Image(systemName: "music.note")
Text("Nu aan het spelen")
.font(.caption)
Spacer()
Button {
// Pauzeer/speel
} label: {
Image(systemName: "play.fill")
}
}
.padding(.horizontal)
}
Wanneer de tab bar inkrimpt tijdens het scrollen, voegt de bottom accessory zich vloeiend samen met de ingekrompen tab bar. Een mooi voorbeeld van hoe Liquid Glass content en navigatie in harmonie laat samenwerken.
Sheets met Liquid Glass
Sheets hebben ook een behoorlijke update gekregen. In iOS 26 zweven gedeeltelijke sheets boven de interface met afgeronde hoeken die de vorm van het apparaat volgen. Ze gebruiken standaard een Liquid Glass-achtergrond.
Het nieuwe standaardgedrag
struct SheetDemoView: View {
@State private var toonSheet = false
var body: some View {
Button("Toon Sheet") {
toonSheet = true
}
.sheet(isPresented: $toonSheet) {
VStack(spacing: 20) {
Text("Liquid Glass Sheet")
.font(.title2.bold())
Text("Deze sheet heeft automatisch een glazen achtergrond en zweeft boven de content.")
.multilineTextAlignment(.center)
Button("Sluit") {
toonSheet = false
}
}
.padding()
.presentationDetents([.medium, .large])
}
}
}
Bij de .medium-detent ziet de sheet er prachtig uit: de randen trekken naar binnen, waardoor een zwevend effect ontstaat dat mooi past bij de ronde hoeken van het scherm. Bij .large wordt de achtergrond geleidelijk ondoorzichtig en hecht de sheet zich aan de schermranden.
Tip: Heb je eerder .presentationBackground() gebruikt voor een aangepaste achtergrond? Overweeg om dat te verwijderen. Laat het Liquid Glass-materiaal gewoon z'n ding doen.
Sheet-morphing vanuit toolbar-knoppen
Dit vind ik persoonlijk een van de mooiste nieuwe mogelijkheden: sheets die morphen vanuit de toolbar-knop die ze presenteert. Het creëert een vloeiende transitie die de sheet visueel verbindt met zijn bron:
struct MorphSheetView: View {
@State private var toonInstellingen = false
@Namespace private var sheetNamespace
var body: some View {
NavigationStack {
ContentUitView()
.toolbar {
ToolbarItem(placement: .primaryAction) {
Button {
toonInstellingen = true
} label: {
Image(systemName: "gear")
}
.matchedTransitionSource(
id: "instellingen",
in: sheetNamespace
)
}
}
.sheet(isPresented: $toonInstellingen) {
InstellingenView()
.navigationTransition(
.zoom(
sourceID: "instellingen",
in: sheetNamespace
)
)
}
}
}
}
Belangrijk detail: de view met de toolbar moet in een NavigationStack of NavigationSplitView staan om de transitie correct te laten werken.
Knopstijlen: .glass en .glassProminent
Naast de .glassEffect()-modifier biedt iOS 26 twee nieuwe knopstijlen die speciaal zijn ontworpen voor Liquid Glass:
VStack(spacing: 20) {
// Glazen knop — voor secundaire acties
Button("Annuleren") {
annuleer()
}
.buttonStyle(.glass)
// Prominente glazen knop — voor primaire acties
Button("Bevestigen") {
bevestig()
}
.buttonStyle(.glassProminent)
}
De richtlijn is simpel: .glass voor secundaire acties, .glassProminent voor de primaire actie. Dat creëert een natuurlijke visuele hiërarchie waardoor gebruikers instinctief weten welke knop de belangrijkste is.
Je kunt tinten combineren met knopstijlen voor extra nadruk:
Button("Verwijderen") {
verwijderItem()
}
.buttonStyle(.glassProminent)
.tint(.red)
Zoekintegratie
De zoekfunctionaliteit in SwiftUI is ook aangepast voor het Liquid Glass-systeem. Op iOS 26 wordt de zoekbalk standaard onderaan het scherm geplaatst:
struct ZoekbareView: View {
@State private var zoekTekst = ""
var body: some View {
NavigationStack {
List {
// Content
}
.searchable(text: $zoekTekst, prompt: "Zoeken...")
}
}
}
Als zoeken niet de primaire ervaring van je scherm is, kun je de nieuwe .searchToolbarBehavior()-modifier gebruiken om het zoekveld te minimaliseren tot een toolbar-knop:
NavigationStack {
List { /* Content */ }
.searchable(text: $zoekTekst)
.searchToolbarBehavior(.minimize)
}
Het systeem kan dit gedrag trouwens ook automatisch toepassen op basis van factoren als schermgrootte of het aantal toolbar-items.
Toegankelijkheid: Een Verantwoordelijkheid
Liquid Glass is visueel prachtig, maar transparante materialen kunnen uitdagingen opleveren voor gebruikers met visuele beperkingen. Daar moeten we als ontwikkelaars rekening mee houden. Gelukkig biedt SwiftUI ingebouwde ondersteuning.
Transparantie verminderen
struct ToegankelijkeGlasView: View {
@Environment(\.accessibilityReduceTransparency)
var verminderdTransparantie
@Environment(\.accessibilityReduceMotion)
var verminderdBeweging
var body: some View {
VStack(spacing: 16) {
Button("Actie") {
voerActieUit()
}
.padding()
.glassEffect(
verminderdTransparantie ? .identity : .regular
)
}
}
}
Het goede nieuws: het Liquid Glass-materiaal past zich al automatisch aan wanneer de gebruiker "Verminder transparantie" heeft ingeschakeld in de systeeminstellingen. Apple's advies is om het systeem dit te laten afhandelen en alleen in te grijpen wanneer het absoluut noodzakelijk is.
Contrast waarborgen
Omdat het glasmateriaal transparant is, moet je ervoor zorgen dat tekst en iconen voldoende contrast hebben met de dynamische achtergrond. Gebruik bij voorkeur systeemkleuren en SF Symbols — die worden automatisch aangepast voor optimale leesbaarheid.
Achterwaartse Compatibiliteit
Natuurlijk draaien niet al je gebruikers direct iOS 26. Voor achterwaartse compatibiliteit kun je een aangepaste view-modifier maken die conditioneel het glaseffect toepast:
struct AdaptiefGlasModifier: ViewModifier {
func body(content: Content) -> some View {
if #available(iOS 26.0, *) {
content.glassEffect(.regular)
} else {
content
.background(.ultraThinMaterial)
.clipShape(Capsule())
}
}
}
extension View {
func adaptiefGlasEffect() -> some View {
modifier(AdaptiefGlasModifier())
}
}
// Gebruik
Button("Actie") { }
.padding()
.adaptiefGlasEffect()
De .ultraThinMaterial in combinatie met een clipping-shape biedt een redelijke benadering van het glaseffect op oudere iOS-versies. Het is niet identiek, maar het voelt visueel verwant genoeg.
Best Practices en Veelgemaakte Fouten
Nu je de technische API's kent, laten we het even hebben over hoe je Liquid Glass goed inzet. Want eerlijk gezegd, je kunt hier makkelijk de mist in gaan als je niet oplet.
Doe: Gebruik glas voor navigatie en besturing
Liquid Glass is ontworpen voor de navigatielaag: toolbars, tab bars, knoppen en besturingselementen. Het moet boven de content zweven en de aandacht naar de content eronder leiden.
// Goed: Glaseffect op navigatie-elementen
NavigationStack {
ScrollView {
LazyVGrid(columns: kolommen) {
ForEach(items) { item in
ItemKaart(item: item)
}
}
}
.toolbar {
ToolbarItem(placement: .primaryAction) {
Button { } label: {
Image(systemName: "plus")
}
// Toolbar-items krijgen automatisch glasstijl
}
}
}
Doe niet: Overmatig glaseffect op content
Een veelgemaakte fout — en ik heb het al meerdere keren voorbij zien komen — is het toepassen van glaseffecten op alle lijstrijen of contentkaarten. Dat resulteert in een overbeladen interface die de eigenlijke bedoeling van Liquid Glass ondermijnt:
// Fout: Glaseffect op elke lijstrij
List(items) { item in
HStack {
Text(item.naam)
Spacer()
Text(item.details)
}
.padding()
.glassEffect() // Niet doen!
}
Gebruik GlassEffectContainer voor gerelateerde elementen
Plaats gerelateerde glaselementen altijd in een GlassEffectContainer. Glas-op-glas zonder gedeelde container leidt tot inconsistente sampling en visuele artefacten:
// Goed: Gedeelde container
GlassEffectContainer {
HStack(spacing: 12) {
Button("A") { }.glassEffect()
Button("B") { }.glassEffect()
Button("C") { }.glassEffect()
}
}
// Fout: Geen container
HStack(spacing: 12) {
Button("A") { }.glassEffect()
Button("B") { }.glassEffect()
Button("C") { }.glassEffect()
}
Verwijder aangepaste achtergronden
Heb je eerder aangepaste achtergronden ingesteld op navigatiebalken, tab bars of sheets? Overweeg dan serieus om die te verwijderen. Het Liquid Glass-materiaal werkt simpelweg het beste wanneer het de onderliggende content kan samplen:
// Verwijder dit soort aanpassingen:
// .scrollContentBackground(.hidden)
// .presentationBackground(Color.white)
// .toolbarBackground(.visible, for: .navigationBar)
// Gebruik in plaats daarvan:
.containerBackground(.clear, for: .navigation)
Een Compleet Voorbeeld: Recepten-app
Laten we alles samenbrengen in een realistisch voorbeeld. Een recepten-app die Liquid Glass volledig benut:
import SwiftUI
struct ReceptenApp: View {
@State private var zoekTekst = ""
@State private var toonNieuwRecept = false
@Namespace private var sheetNamespace
let recepten = Recept.voorbeeldData
var body: some View {
NavigationStack {
ScrollView {
LazyVStack(spacing: 16) {
ForEach(recepten) { recept in
NavigationLink(value: recept) {
ReceptKaart(recept: recept)
}
}
}
.padding()
}
.navigationTitle("Mijn Recepten")
.searchable(text: $zoekTekst, prompt: "Zoek een recept...")
.toolbar {
ToolbarItemGroup(placement: .bottomBar) {
Button { } label: {
Label("Filter", systemImage: "line.3.horizontal.decrease")
}
ToolbarSpacer(.flexible)
Button {
toonNieuwRecept = true
} label: {
Label("Nieuw recept", systemImage: "plus")
}
.matchedTransitionSource(
id: "nieuwRecept",
in: sheetNamespace
)
}
}
.sheet(isPresented: $toonNieuwRecept) {
NieuwReceptView()
.presentationDetents([.medium, .large])
.navigationTransition(
.zoom(
sourceID: "nieuwRecept",
in: sheetNamespace
)
)
}
.navigationDestination(for: Recept.self) { recept in
ReceptDetailView(recept: recept)
}
}
}
}
struct ReceptKaart: View {
let recept: Recept
var body: some View {
VStack(alignment: .leading, spacing: 8) {
Image(recept.afbeelding)
.resizable()
.aspectRatio(16/9, contentMode: .fill)
.clipShape(RoundedRectangle(cornerRadius: 12))
Text(recept.naam)
.font(.headline)
HStack {
Label(
"\(recept.bereidingstijd) min",
systemImage: "clock"
)
Spacer()
Label(
recept.moeilijkheid,
systemImage: "chart.bar"
)
}
.font(.caption)
.foregroundStyle(.secondary)
}
.padding()
}
}
In dit voorbeeld werken de toolbar, zoekbalk, sheet en navigatie allemaal samen met het Liquid Glass-systeem. De toolbar-items zweven op een glazen oppervlak, de sheet morpht vanuit de plus-knop, en de zoekbalk past zich vanzelf aan. Dat is het mooie van dit systeem — de onderdelen versterken elkaar.
Prestatie-overwegingen
Liquid Glass-effecten zijn GPU-intensief vanwege de real-time vervaging, lichtbreking en compositing. Daar moet je rekening mee houden, zeker als je veel elementen op het scherm hebt.
- Beperk het aantal glaseffecten per scherm: Elk glaseffect vereist een aparte render-pass. Te veel tegelijkertijd kan de frame rate negatief beïnvloeden, vooral op oudere apparaten.
- Gebruik GlassEffectContainer: De container optimaliseert de rendering door meerdere glaseffecten samen te voegen. Dit is niet alleen visueel beter, maar ook performanter.
- Vermijd glaseffecten in ScrollView-cellen: Honderden cellen met glaseffecten in een scrollbare lijst is simpelweg een recept voor stotteren. Gebruik glaseffecten voor vaste navigatie-elementen, niet voor herhaalde content.
- Test op echte apparaten: De Simulator geeft geen accuraat beeld van de prestaties. Test altijd op fysieke apparaten, met name oudere modellen zoals de iPhone 15 of eerder.
Conclusie
Liquid Glass is meer dan een cosmetische update — het is een fundamentele verschuiving in hoe Apple-apps eruitzien en aanvoelen. De focus op gelaagdheid, transparantie en vloeiende transities creëert een moderne gebruikerservaring die content centraal stelt.
Als SwiftUI-ontwikkelaar heb je het geluk dat veel van deze schoonheid gratis komt. Compileer je app met Xcode 26 en de standaardelementen krijgen automatisch het nieuwe uiterlijk. Maar om die extra polish toe te voegen die gebruikers echt opvalt, moet je de API's begrijpen die we hier hebben behandeld.
De belangrijkste takeaways:
- Gebruik
.glassEffect()voor navigatie- en besturingselementen, niet voor content - Groepeer gerelateerde glaselementen in een
GlassEffectContainer - Benut morph-transities met
.glassEffectID()voor een gepolijste ervaring - Respecteer de toegankelijkheidsinstellingen van je gebruikers
- Verwijder aangepaste achtergronden en laat het glazen materiaal stralen
Met Foundation Models voor on-device AI, de verbeterde concurrency in Swift 6.2 en nu Liquid Glass voor een verbluffende UI — iOS 26 is zonder twijfel een van de meest opwindende releases voor ontwikkelaars in jaren. Tijd om te gaan bouwen.