Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
379 views
in Technique[技术] by (71.8m points)

ios - Make ScrollView jump to the top when the offset becomes a certain value (assuming starting offset is NOT zero)

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:

  1. 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:

  1. 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.

  2. 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()
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)
等待大神答复

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...