Get the current scroll position of a SwiftUI ScrollView
It was possible to read it and before. Here is a solution based on view preferences.
struct DemoScrollViewOffsetView: View {
@State private var offset = CGFloat.zero
var body: some View {
ScrollView {
VStack {
ForEach(0..<100) { i in
Text("Item \(i)").padding()
}
}.background(GeometryReader {
Color.clear.preference(key: ViewOffsetKey.self,
value: -$0.frame(in: .named("scroll")).origin.y)
})
.onPreferenceChange(ViewOffsetKey.self) { print("offset >> \($0)") }
}.coordinateSpace(name: "scroll")
}
}
struct ViewOffsetKey: PreferenceKey {
typealias Value = CGFloat
static var defaultValue = CGFloat.zero
static func reduce(value: inout Value, nextValue: () -> Value) {
value += nextValue()
}
}
Save ScrollViews position and scroll back to it later (offset to position)
You don't need actually offset in this scenario, just store id of currently visible view (you can use any appropriate algorithm for your data of how to detect it) and then scroll to view with that id.
Here is a simplified demo of possible approach. Tested with Xcode 12.1/iOS 14.1
struct TestScrollBackView: View {
@State private var stored: Int = 0
@State private var current: [Int] = []
var body: some View {
ScrollViewReader { proxy in
VStack {
HStack {
Button("Store") {
// hard code is just for demo !!!
stored = current.sorted()[1] // 1st is out of screen by LazyVStack
print("!! stored \(stored)")
}
Button("Restore") {
proxy.scrollTo(stored, anchor: .top)
print("[x] restored \(stored)")
}
}
Divider()
ScrollView {
LazyVStack {
ForEach(0..<1000, id: \.self) { obj in
Text("Item: \(obj)")
.onAppear {
print(">> added \(obj)")
current.append(obj)
}
.onDisappear {
current.removeAll { $0 == obj }
print("<< removed \(obj)")
}.id(obj)
}
}
}
}
}
}
}
Set scroll position from a different view in scrollview
What a horrible MRE!! This is what you could mean and how it works:
One. you have to put .id()s on your ScrollView, otherwise scollTo doesn't know where to go.
Two. There have to be enough entries in the ScrollView. If all are visible, the scrollTo won't do anything.
class EnvironmentVariables: ObservableObject {
@Published var currentIndexforPosts: Int = 0
}
struct ContentView: View {
@StateObject var environmentVariables = EnvironmentVariables()
var body: some View {
VStack {
ButtonView()
ScrollView1()
}
.environmentObject(environmentVariables)
}
}
struct ScrollView1: View {
@EnvironmentObject var environmentVariables: EnvironmentVariables
var body: some View {
ScrollView {
ScrollViewReader { value in
LazyVStack {
ForEach(0..<100) { i in
Text ("Text \(i)").id(i)
.font(.title)
}
}
.onChange(of: environmentVariables.currentIndexforPosts) { _ in
if environmentVariables.currentIndexforPosts >= 0 {
withAnimation {
value.scrollTo(environmentVariables.currentIndexforPosts, anchor: .top)
}
}
}
}
}
}
}
struct ButtonView: View {
@EnvironmentObject var environmentVariables: EnvironmentVariables
var body: some View {
Button("Go to next") {
environmentVariables.currentIndexforPosts += 10
}
.padding()
Button("Go to previous") {
environmentVariables.currentIndexforPosts -= 10
}
}
}
Related Topics
Cordova App Hanging During Startup on iOS 10
Nslog on Devices in iOS 10/Xcode 8 Seems to Truncate - Why
Detecting Uibutton Pressed in Tableview: Swift Best Practices
How to Animate the Background Color of a Uilabel
How to Determine the Os Version At Runtime in Os X or iOS (Without Using Gestalt)
How to Get the Color of a Pixel in a Uiimage With Swift
Changing Specific Text's Color Using Nsmutableattributedstring in Swift
When Should We Use "Embedded Binaries" Rather Than "Linked Frameworks" in Xcode
Blank Space at Top of Uitextview in iOS 10
How to Change Height of Navigation Bar - Swift 3
Passing Data Between View Controllers Using Segue
Swift: Issue in Converting String to Double
Ios: How to Share Text and Image on Social Networks
How to Make Outlet Connection to a Constraint in Ib
Swiftui - How to Pass Environmentobject into View Model
How to Ignore Touch Events and Pass Them to Another Subview'S Uicontrol Objects
What's the Best Way to Detect When the App Is Entering the Background For My View