Using this answer from Asperi, I’ve managed to determine the offset of my ScrollView as it scrolls. I’ve made an addition to it by including a ScrollViewReader so I can jump to specific locations.
What I’m doing:
- when the view loads, I get it to automatically jump to a specific row. In the example’s case, following Asperi’s demo, I’m making it to move the 50th item. This works fine.
What I’m trying to do but not getting it to work:
I want it so that when you move upwards (i.e. scroll up/swipe down), for the view to automatically jump to the top when a certain location is passed. I’m using the offset determined at the moment as the trigger point (i.e. when the offset is below a certain number). Ideally, I would be using something else, such as when an identifiable UI becomes visible. This is 1/3 things I’m after, but probably the least important of the three. The bigger issue is that my check only seems to work if I’m passing the trigger offset carefully. That is, I’m moving slowly. If I do a non-slow (doesn’t have to be fast) swipe, it will pass the offset without doing anything. I’ve tried to improve this by making it check for a specific offset range rather than just a single number, and although this has improved things, it’s still not working consistently.
Finally, ideally when you have been taken to the top, I would like any swipe up/scroll down, to jump you back to where you were before 2)’s logic kicked in e.g. the 50th item in my example.
If I can get guidance on any, hopefully all, of the above then it would be greatly appreciated.
Here’s the code:
struct DemoScrollViewOffsetView: View {
@State private var offset = CGFloat.zero
var body: some View {
ScrollView {
ScrollViewReader { value in
VStack {
ForEach(0..<100) { i in
Text("Item (i)")
.padding()
.id(i)
}
}.background(GeometryReader {
Color.clear.preference(key: ViewOffsetKey.self,
value: -$0.frame(in: .named("scroll")).origin.y)
})
.onAppear() {
value.scrollTo(50, anchor: .top) /// jump to 50th row when launching
}
.onPreferenceChange(ViewOffsetKey.self) {
print("offset >> ($0)")
if Int($0) <= 1000 && Int($0) >= 995 { /// when offset between 995 and 1000, jump to the top
withAnimation {
value.scrollTo(1)
}
}
}
}
}.coordinateSpace(name: "scroll")
}
}
struct ViewOffsetKey: PreferenceKey {
typealias Value = CGFloat
static var defaultValue = CGFloat.zero
static func reduce(value: inout Value, nextValue: () -> Value) {
value += nextValue()
}
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…