2026 DesignSwiftUI & UI Frameworks
WWDC26 · 18 min · Design / SwiftUI & UI Frameworks
Compose advanced graphics effects with SwiftUI
Discover how to craft rich, custom experiences by creatively composing SwiftUI layout and graphics APIs. We’ll show you how to break down complex designs and use a creative pipeline to chain simple building blocks together. Learn how to draw with layer shaders, animate with timelines, and anchor views with alignment guides.
Watch at developer.apple.com ↗Chapters
Code shown on screen · 17 snippets
Cover art image
Image("CoverArt") Blurred cover art image
Image("CoverArt")
.blur(radius: 30) Applying layer effect in SwiftUI
GeometryReader { proxy in
CoverArtView()
.layerEffect(
ShaderLibrary.backgroundWarp(),
maxSampleOffset: .zero
)
}
.ignoresSafeArea() Writing layer effect shader in Metal
[[stitchable]] half4 backgroundWarp(
float2 position, SwiftUI::Layer layer
) {
return layer.sample(position);
} Metal shader with offset parameter
[[stitchable]] half4 backgroundWarp(
float2 position, SwiftUI::Layer layer,
float2 offset
) {
return layer.sample(position + offset);
} SwiftUI layer effect with offset parameter
GeometryReader { proxy in
CoverArtView()
.layerEffect(
ShaderLibrary.backgroundWarp(
.float2(.init(x: 0, y: 0))
),
maxSampleOffset: .zero
)
}
.ignoresSafeArea() SwiftUI layer effect with full-width offset
GeometryReader { proxy in
CoverArtView()
.layerEffect(
ShaderLibrary.backgroundWarp(
.float2(.init(x: proxy.size.width, y: 0))
),
maxSampleOffset: .zero
)
}
.ignoresSafeArea() SwiftUI layer effect with noise sampling
GeometryReader { proxy in
CoverArtView()
.layerEffect(
ShaderLibrary.backgroundWarp(
.float2(proxy.size),
.image(Image("NoiseTexture"))
),
maxSampleOffset: .zero
)
}
.ignoresSafeArea() Metal shader with noise sampling
[[stitchable]] half4 backgroundWarp(
float2 position, SwiftUI::Layer layer,
float2 size, texture2d<half> noiseTex
) {
constexpr sampler s(address::repeat, filter::linear);
float2 uv = position / size;
half4 n = noiseTex.sample(s, uv);
float2 offset = (float2(n.r, n.g) - 0.5) * 200.0;
return layer.sample(position + offset);
} Metal shader with domain warping
[[stitchable]] half4 backgroundWarp(
float2 position, SwiftUI::Layer layer,
float2 size, texture2d<half> noiseTex
) {
constexpr sampler s(address::repeat, filter::linear);
float2 uv = position / size;
half4 n = noiseTex.sample(s, uv);
float2 q = float2(n.r, n.g);
n = noiseTex.sample(s, uv + q);
float2 offset = (float2(n.r, n.g) - 0.5) * 200.0;
return layer.sample(position + offset);
} SwiftUI layer effect with static visual
GeometryReader { proxy in
CoverArtView()
.layerEffect(
ShaderLibrary.backgroundWarp(
.float2(proxy.size),
.image(Image("NoiseTexture"))
),
maxSampleOffset: .zero
)
}
.ignoresSafeArea() SwiftUI layer effect with animated visual
private var startDate = Date.now
TimelineView(.animation) { timeline in
let elapsed = timeline.date.timeIntervalSince(
startDate
)
CoverArtView()
.layerEffect(
ShaderLibrary.backgroundWarp(
.float2(proxy.size),
.image(Image("NoiseTexture")),
.float(elapsed)
),
maxSampleOffset: .zero
)
} Basic transcript view
ScrollView {
LazyVStack(alignment: .leading, spacing: 12) {
ForEach(sampleTranscript) { line in
.font(.title)
.fontWeight(.bold)
}
}
} Time-synced transcript view
private var playback = PlaybackState()
ScrollViewReader { scrollProxy in
ScrollView {
LazyVStack(alignment: .leading, spacing: 12) {
ForEach(sampleTranscript) { line in
Text(line.text)
.transcriptLineStyle(isCurrent:
line.id == playback.currentLineIndex
)
}
}
}
.onChange(of: playback.currentLineIndex, { _, i in
scrollProxy.scrollTo(i, anchor: .center)
})
} Overlay with center alignment
Text(line.text)
.overlay {
Text(line.formattedTimestamp)
} Overlay with bottom leading alignment
Text(line.text)
.overlay(alignment: .bottomLeading) {
Text(line.formattedTimestamp)
} Overlay with alignment guide override
Text(line.text)
.overlay(alignment: .bottomLeading) {
Text(line.formattedTimestamp)
.alignmentGuide(.bottom) { $0[.top] }
} Resources
Related sessions
-
26 min