AcaMate_iOS/AcaMate/1. View/10. Common/OffsetObservableScollView.swift
2025-02-11 08:57:42 +09:00

75 lines
2.5 KiB
Swift

//
// OffsetObservableScollView.swift
// AcaMate
//
// Created by TAnine on 2/10/25.
//
import SwiftUI
import Combine
struct OffsetObservableScrollView<Content: View>: View {
var axes: Axis.Set = .vertical
var showsIndicators: Bool = true
@Binding var scrollOffset: CGPoint
@ViewBuilder var content: (ScrollViewProxy) -> Content
@Namespace var coordinateSpaceName: Namespace.ID
init(
_ axes: Axis.Set = .vertical,
showsIndicators: Bool = true,
scrollOffset: Binding<CGPoint>,
@ViewBuilder content: @escaping (ScrollViewProxy) -> Content
) {
self.axes = axes
self.showsIndicators = showsIndicators
self._scrollOffset = scrollOffset
self.content = content
}
var body: some View {
ScrollView(axes, showsIndicators: showsIndicators) {
ScrollViewReader { scrollViewProxy in
VStack(spacing: 0) {
// anchor (id "TOP")
Color.clear
.frame(height: 1)
.id("TOP")
// . content scrollViewProxy ,
// .
content(scrollViewProxy)
.overlay {
GeometryReader { geometryProxy in
Color.clear
.preference(
key: ScrollOffsetPreferenceKey.self,
value: CGPoint (
x: -geometryProxy.frame(in: .named(coordinateSpaceName)).minX,
y: -geometryProxy.frame(in: .named(coordinateSpaceName)).minY
)
)
}
}
}
}
}
.coordinateSpace(name: coordinateSpaceName)
.onPreferenceChange(ScrollOffsetPreferenceKey.self) { value in
printLog("\(scrollOffset) -> \(value)")
scrollOffset = value
}
}
}
struct ScrollOffsetPreferenceKey: PreferenceKey {
static var defaultValue: CGPoint = .zero
static func reduce(value: inout CGPoint, nextValue: () -> CGPoint) {
value = nextValue()
}
}