-
Notifications
You must be signed in to change notification settings - Fork 0
/
ObservableScrollView.swift
50 lines (42 loc) · 1.38 KB
/
ObservableScrollView.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
//
// ObservableScrollView.swift
// PhotoRoute
//
// Created by Manuel Roth on 09.02.23.
//
import SwiftUI
// Simple preference that observes a CGFloat.
struct ScrollViewOffsetPreferenceKey: PreferenceKey {
static var defaultValue = CGFloat.zero
static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
value += nextValue()
}
}
// A ScrollView wrapper that tracks scroll offset changes.
struct ObservableScrollView<Content>: View where Content : View {
@Namespace var scrollSpace
@Binding var rowIndex: Int
private var rowHeight: CGFloat
let content: (ScrollViewProxy) -> Content
init(rowIndex: Binding<Int>, rowHeight: CGFloat, @ViewBuilder content: @escaping (ScrollViewProxy) -> Content) {
_rowIndex = rowIndex
self.rowHeight = rowHeight
self.content = content
}
var body: some View {
ScrollView {
ScrollViewReader { proxy in
content(proxy)
.background(GeometryReader { geo in
let offset = -geo.frame(in: .named(scrollSpace)).minY
Color.clear.preference(key: ScrollViewOffsetPreferenceKey.self, value: offset)
})
}
}
.coordinateSpace(name: scrollSpace)
.onPreferenceChange(ScrollViewOffsetPreferenceKey.self) { value in
let index = Int((value + rowHeight * 1.5) / rowHeight) - 1
self.rowIndex = max(0, index)
}
}
}