Is it possible to SET ScrollView offset in SwiftUI?
I have made a custom tab bar that uses a Switch/Case to change views. However my views all contain vertical ScrollViews. I understand that each time I switch between Views they are destroyed, and thus the scrollView offset is lost.
I have used the following approach to GET ScrollView Offset, however I am now not sure how I can use this information. I have seen there is now ScrollTo but this seems to only work with an ID.
Is it possible to use ScrollTo with an Offset in some way?
In general, what I'm trying to achieve is standard Tab bar behaviour where a user returns to the same position they left each Tab
Any help is appreciated. Also, please let me know if this is bad for performance as I am a novice. Thanks.
private struct ScrollViewOffsetPreferenceKey: PreferenceKey {
static var defaultValue: CGPoint = .zero
static func reduce(value: inout CGPoint, nextValue: () -> CGPoint) { }
}
struct ScrollViewWithOffset<T: View>: View {
let axes: Axis.Set
let showsIndicator: Bool
let offsetChanged: (CGPoint) -> Void
let content: T
init(axes: Axis.Set = .vertical,
showsIndicator: Bool = false,
offsetChanged: @escaping (CGPoint) -> Void = { _ in },
@ViewBuilder content: () -> T
) {
self.axes = axes
self.showsIndicator = showsIndicator
self.offsetChanged = offsetChanged
self.content = content()
}
var body: some View {
ScrollView(axes, showsIndicators: showsIndicator) {
GeometryReader { proxy in
Color.clear.preference(
key: ScrollViewOffsetPreferenceKey.self,
value: proxy.frame(in: .named("scrollView")).origin
)
}
.frame(width: 0, height: 0)
content
}
.coordinateSpace(name: "scrollView")
.onPreferenceChange(ScrollViewOffsetPreferenceKey.self, perform: offsetChanged)
}
}
Used like so...
ScrollViewWithOffset { point in
scrollViewOffset = point.y
} content: {
ScrollViewReader { proxy in
LazyVStack(spacing: 4) {
ForEach(0..<10, id: \.self) { i in
Item()
.id(i)
}
}
}
}