Last active
October 13, 2024 02:49
-
-
Save marquavious/6535ee430bd9ed81899c20c9e81197bb to your computer and use it in GitHub Desktop.
Swift-UI-Stretchy-Header-View
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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)) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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