Skip to content

Instantly share code, notes, and snippets.

@samsonjs
Created March 8, 2025 18:17
Show Gist options
  • Save samsonjs/d2973f1c61014671601b442ca7eb8d97 to your computer and use it in GitHub Desktop.
Save samsonjs/d2973f1c61014671601b442ca7eb8d97 to your computer and use it in GitHub Desktop.
Dynamic SwiftUI view that pins a header above a scroll view's contents, except at larger dynamic type sizes where it makes the header part of the scrolling content.
import SwiftUI
/// Dynamic SwiftUI view that pins a header above a scroll view's contents, except at larger dynamic type sizes where it makes the header part of the scrolling content.
struct DynamicTypePinnedHeaderView<Header: View, Footer: View, Content: View>: View {
let inlineThreshold: DynamicTypeSize
let header: Header
let footer: Footer
let content: Content
@Environment(\.dynamicTypeSize) private var typeSize
init(
inlineThreshold: DynamicTypeSize = .accessibility1,
@ViewBuilder header: () -> Header,
@ViewBuilder footer: () -> Footer,
@ViewBuilder content: () -> Content
) {
self.inlineThreshold = inlineThreshold
self.header = header()
self.footer = footer()
self.content = content()
}
var body: some View {
if typeSize >= inlineThreshold {
VStack(spacing: 0) {
ScrollView {
VStack(spacing: 0) {
header
content
}
}
footer
}
} else {
VStack(spacing: 0) {
header
ScrollView {
content
}
footer
}
}
}
}
#Preview {
DynamicTypePinnedHeaderView(header: {
DynamicTypeAdaptiveStack(verticalThreshold: .accessibility1) {
Group {
Text("cool stuff up here")
Text("lots")
Text("of")
Text("it,")
Text("too!")
}
.padding(.vertical)
}
.bold()
.padding()
.frame(maxWidth: .infinity)
.background(Color.accentColor)
}, footer: {
Button {} label: {
Label("reticulate splines", systemImage: "tortoise")
.padding(.vertical, 8)
.frame(maxWidth: .infinity)
}
.buttonStyle(.borderedProminent)
.padding()
}, content: {
VStack {
ForEach(0..<200) { _ in
Text("all work and no play makes jack a dull boy")
}
}
.frame(maxWidth: .infinity)
.background(Color(.secondarySystemBackground))
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment