Skip to content

Instantly share code, notes, and snippets.

@LucasAbijmil
Created March 4, 2023 12:17
Show Gist options
  • Save LucasAbijmil/b95c7c49c05b6af59e077caf0f621a2e to your computer and use it in GitHub Desktop.
Save LucasAbijmil/b95c7c49c05b6af59e077caf0f621a2e to your computer and use it in GitHub Desktop.
LazyScrollView – Before iOS 16.4 otherwise use the `scrollBounceBehavior` modifier
struct LazyScrollView<Content: View>: View {
@State private var fitsVertically = false
@State private var fitsHorizontally = false
private let content: Content
private let axes: Axis.Set
private let showsIndicators: Bool
private var activeScrollingDirections: Axis.Set {
return axes.intersection((fitsVertically ? [] : Axis.Set.vertical).union(fitsHorizontally ? [] : Axis.Set.horizontal))
}
init(_ axes: Axis.Set = .vertical, showsIndicators: Bool = true, @ViewBuilder content: () -> Content) {
self.axes = axes
self.showsIndicators = showsIndicators
self.content = content()
}
var body: some View {
GeometryReader { geometryReader in
ScrollView(activeScrollingDirections, showsIndicators: showsIndicators) {
content
.background {
GeometryReader {
Color.clear.preference(key: ViewSizeKey.self, value: $0.frame(in: .local).size)
}
}
}
.onPreferenceChange(ViewSizeKey.self) {
fitsVertically = $0.height <= geometryReader.size.height
fitsHorizontally = $0.width <= geometryReader.size.width
}
}
}
}
private struct ViewSizeKey: PreferenceKey {
static var defaultValue: CGSize {
return .zero
}
static func reduce(value: inout Value, nextValue: () -> Value) {
let next = nextValue()
value = CGSize(width: value.width + next.width, height: value.height + next.height)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment