Skip to content

Instantly share code, notes, and snippets.

@marquavious
Last active October 13, 2024 02:49
Show Gist options
  • Save marquavious/6535ee430bd9ed81899c20c9e81197bb to your computer and use it in GitHub Desktop.
Save marquavious/6535ee430bd9ed81899c20c9e81197bb to your computer and use it in GitHub Desktop.
Swift-UI-Stretchy-Header-View
// https://alladinian.hashnode.dev/stretchy-views-in-swiftui
import SwiftUI
struct ContehntView: View {
let overlay: some View =
Text("❊ Stretchy")
.font(.title)
.fontWeight(.bold)
.padding()
.shadow(radius: 4)
var body: some View {
ScrollView(showsIndicators: false) {
VStack {
Image("header")
.resizable()
.stretchy()
.overlay(overlay, alignment: .bottomLeading)
.frame(height: 180)
ForEach(0..<10) { i in
Color.white.opacity(0.1)
.frame(height: 80)
.cornerRadius(12)
.padding(8)
}
Image("footer")
.resizable()
.stretchy(isTop: false)
.overlay(overlay, alignment: .topLeading)
.frame(height: 180)
}
}
.edgesIgnoringSafeArea(.vertical)
}
struct Stretchy: ViewModifier {
var isTop = true
func heightFor(_ reader: GeometryProxy) -> CGFloat {
let height = reader.size.height
let frame = reader.frame(in: .global)
let deltaY = isTop ? frame.minY : (UIScreen.main.bounds.size.height - frame.maxY)
return height + max(0, deltaY)
}
func offsetFor(_ reader: GeometryProxy) -> CGFloat {
guard isTop else { return 0 }
let frame = reader.frame(in: .global)
let deltaY = frame.minY
return min(0, -deltaY)
}
func body(content: Content) -> some View {
GeometryReader { reader in
Color.clear
.overlay(content.aspectRatio(contentMode: .fill), alignment: .center)
.clipped()
.frame(height: heightFor(reader))
.offset(y: offsetFor(reader))
}
}
}
}
extension View {
func stretchy(isTop: Bool = true) -> some View {
self.modifier(Stretchy(isTop: isTop))
}
}
struct StretchyHeaderScrollView<Content: View>: View {
var photoHeight: CGFloat
let viewBuilder: () -> Content
var body: some View {
ScrollView(showsIndicators: false) {
VStack {
Image(.rainbowlake)
.resizable()
.stretchy()
.frame(height: photoHeight)
viewBuilder()
}
}
.edgesIgnoringSafeArea(.vertical)
}
}
#Preview {
StretchyHeaderScrollView(photoHeight: 180) {
Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment