aboutsummaryrefslogtreecommitdiff
path: root/Hotline/Library/Utility/ObservableScrollView.swift
blob: 05688f141907c2f16440f25b855472a5ad01cd41 (plain)
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
import SwiftUI

struct ScrollViewOffsetPreferenceKey: PreferenceKey {
  typealias Value = CGFloat
  static var defaultValue = CGFloat.zero
  static func reduce(value: inout Value, nextValue: () -> Value) {
    value += nextValue()
  }
}

struct ObservableScrollView<Content>: View where Content: View {
  @Namespace var scrollSpace
  @Binding var scrollOffset: CGFloat
  let content: () -> Content

  init(
    scrollOffset: Binding<CGFloat>,
    @ViewBuilder content: @escaping () -> Content
  ) {
    _scrollOffset = scrollOffset
    self.content = content
  }

  var body: some View {
    ScrollView {
      content()
        .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
      scrollOffset = value
    }
  }
}