从Observer或外部View调用ScrollView的scrollTo

C. *_*dal 4 swiftui

当用户选择选项卡时,我试图重置我的 ScrollView。问题是所有教程都是针对嵌套在 ScrollView 内的按钮。我的 ScrollView 与我需要点击以重置 ScrollView 的位置完全分开。

我找到了这个教程 - https://www.hackingwithswift.com/forums/swiftui/have-a-button-outside-of-scrollviewreader-be-able-to-scroll-the-scrollview-to-a-position/2741

但我收到错误“无法在范围内找到代理”。

   @EnvironmentObject var global: GlobalObserver    
   return ScrollView {
          ScrollViewReader { (proxy: ScrollViewProxy) in
             EmptyView()
          }.onChange(of: self.global.resetScroll){ resetScroll in
                if (resetScroll){
                    proxy.scrollTo(0)
                    self.global.resetScroll = false
                }
            }
Run Code Online (Sandbox Code Playgroud)

如果有人知道在视图之外设置 ScrollView 位置的更简单的实现,我会很高兴听到它。

paw*_*222 6

根据问题中的链接调整示例,您的代码可能如下所示:

struct ContentView: View {
    @State private var scrollTarget: Int?

    var body: some View {
        Button("Reset") {
            scrollTarget = 0
        }
        ScrollViewReader { proxy in
            ScrollView {
                VStack {
                    ForEach(0...50, id: \.self) {
                        Text("\($0)")
                    }
                }
            }
            .onChange(of: scrollTarget) { target in
                if let target = target {
                    scrollTarget = nil
                    withAnimation {
                        proxy.scrollTo(target)
                    }
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果需要,您可以移动scrollTarget到 anObservableObject并从视图外部调用它:

class GlobalObserver: ObservableObject {
    @Published var scrollTarget: Int?
}

struct ContentView: View {
    @EnvironmentObject var global: GlobalObserver

    var body: some View {
        ScrollViewReader { proxy in
            ScrollView {
                VStack {
                    ForEach(0...50, id: \.self) {
                        Text("\($0)")
                    }
                }
            }
            .onChange(of: global.scrollTarget) { target in
                if let target = target {
                    global.scrollTarget = nil
                    withAnimation {
                        proxy.scrollTo(target)
                    }
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)