我正在尝试在SwiftUI中创建两个同步的ScrollViews
,以便在一个中滚动会导致另一个也滚动。
我在使用底部显示的ScrollViewOffset
类获取scrollView偏移值时遇到了问题,但不知道如何滚动另一个视图。
我似乎可以通过阻止一个视图的滚动并在另一个视图上设置内容位置(position())来“hack”它 - 是否有任何方法实际滚动scrollView内容到位置? 我知道ScrollViewReader似乎允许滚动以显示内容项,但我似乎找不到任何将内容滚动到偏移位置的东西。
使用position()的问题是它实际上不会更改ScrollViews滚动条位置 - 似乎没有ScrollView.scrollContentsTo(point: CGPoint)。
@State private var scrollOffset1: CGPoint = .zero
HStack {
ScrollViewOffset(onOffsetChange: { offset in
scrollOffset1 = offset
print("New ScrollView1 offset: \(offset)")
}, content: {
VStack {
ImageView(filteredImageProvider: self.provider)
.frame(width: imageWidth, height: imageHeight)
}
.frame(width: imageWidth + (geometry.size.width - 20) * 2, height: imageHeight + (geometry.size.height - 20) * 2)
.border(Color.white)
.id(0)
})
ScrollView([]) {
VStack {
ImageView(filteredImageProvider: self.provider, showEdits: false)
.frame(width: imageWidth, height: imageHeight)
}
.frame(width: imageWidth + (geometry.size.width - 20) * 2, height: imageHeight + (geometry.size.height - 20) * 2)
.border(Color.white)
.id(0)
.position(x: scrollOffset1.x, y: scrollOffset1.y + (imageHeight + (geometry.size.height - 20) * 2)/2)
}
}
//
// ScrollViewOffset.swift
// ZoomView
//
//
import Foundation
import SwiftUI
struct ScrollViewOffset<Content: View>: View {
let onOffsetChange: (CGPoint) -> Void
let content: () -> Content
init(
onOffsetChange: @escaping (CGPoint) -> Void,
@ViewBuilder content: @escaping () -> Content
) {
self.onOffsetChange = onOffsetChange
self.content = content
}
var body: some View {
ScrollView([.horizontal, .vertical]) {
offsetReader
content()
.padding(.top, -8)
}
.coordinateSpace(name: "frameLayer")
.onPreferenceChange(ScrollOffsetPreferenceKey.self, perform: onOffsetChange)
}
var offsetReader: some View {
GeometryReader { proxy in
Color.clear
.preference(
key: ScrollOffsetPreferenceKey.self,
value: proxy.frame(in: .named("frameLayer")).origin
)
}
.frame(width: 0, height: 0)
}
}
private struct ScrollOffsetPreferenceKey: PreferenceKey {
static var defaultValue: CGPoint = .zero
static func reduce(value: inout CGPoint, nextValue: () -> CGPoint) {}
}