在SwiftUI ScrollView中获取和设置内容的位置

cho*_*rry 8 uiscrollview swiftui

我有一个水平滚动视图,我想以编程方式设置位置。这是视图的主体:

let radius = CGFloat(25)
let scrollWidth = CGFloat(700)
let scrollHeight = CGFloat(100)
let spacing = CGFloat(20)
let circleDiameter = CGFloat(50)

...

    var body: some View {
        GeometryReader { viewGeometry in
            ScrollView () {
                VStack(spacing: 0) {
                    Spacer(minLength: spacing)

                    Circle()
                        .fill(Color.black.opacity(0.5))
                        .scaledToFit()
                        .frame(width: circleDiameter, height: circleDiameter)

                    ScrollView(.horizontal) {
                        Text("The quick brown fox jumps over the lazy dog. Finalmente.")
                            .font(Font.title)
                            .frame(width: scrollWidth, height: scrollHeight)
                            .foregroundColor(Color.white)
                            .background(Color.white.opacity(0.25))
                    }
                    .frame(width: viewGeometry.size.width, height: scrollHeight)
                    .padding([.top, .bottom], spacing)

                    Circle()
                        .fill(Color.white.opacity(0.5))
                        .scaledToFit()
                        .frame(width: circleDiameter, height: circleDiameter)

                    Spacer(minLength: spacing)
                }
                .frame(width: viewGeometry.size.width)
            }
            .background(Color.orange)
        }
        .frame(width: 324 / 2, height: spacing * 4 + circleDiameter * 2 + scrollHeight) // testing
        .cornerRadius(radius)
        .background(Color.black)
    }
Run Code Online (Sandbox Code Playgroud)

如何更改此代码,以便可以获取“快速褐狐”的当前位置并在以后还原它?我只是想做一些像contentOffsetUIKit 一样的事情。

我可以看到a GeometryReader可能对于获取内容的当前框架有用,但是没有等效的编写器。为滚动视图或文本设置a .position().offset()也没有使我感到困惑。

非常感激任何的帮助!

小智 5

我一直在玩一个解决方案,并发布了我在以编程方式设置内容偏移量方面所做的工作的要点 https://gist.github.com/jfuellert/67e91df63394d7c9b713419ed8e2beb7


Fab*_*yne 2

使用常规的 SwiftUI ScrollView,据我所知,您可以使用带有 proxy.frame(in: .global).minY 的 GeometryReader 获取位置(请参阅下面的修改示例),但无法设置“contentOffset”。

实际上,如果您查看调试视图层次结构,您会注意到我们的内容视图嵌入到滚动视图的内部 SwiftUI 其他内容视图中。因此,您将偏移此内部视图,而不是滚动视图。

经过一段时间的搜索后,我找不到任何使用 SwiftUI ScrollView 来实现这一点的方法(我想这需要等待 Apple)。我能做的最好的事情(通过黑客)是滚动到底部。

更新:我之前犯了一个错误,因为它是在垂直滚动条上。现已更正。

class SGScrollViewModel: ObservableObject{
    var scrollOffset:CGFloat = 0{
        didSet{
            print("scrollOffset: \(scrollOffset)")
        }
    }

}


struct ContentView: View {
    public var scrollModel:SGScrollViewModel = SGScrollViewModel()

    let radius = CGFloat(25)
     let scrollWidth = CGFloat(700)
     let scrollHeight = CGFloat(100)
     let spacing = CGFloat(20)
     let circleDiameter = CGFloat(50)

         var body: some View {
            var topMarker:CGFloat = 0
            let scrollTopMarkerView =  GeometryReader { proxy -> Color in
                topMarker = proxy.frame(in: .global).minX
                return Color.clear
            }
            let scrollOffsetMarkerView =  GeometryReader { proxy -> Color in
                self.scrollModel.scrollOffset = proxy.frame(in: .global).minX - topMarker
                return Color.clear
            }

            return GeometryReader { viewGeometry in                    
                 ScrollView () {
                     VStack(spacing: 0) {

                        Spacer(minLength: self.spacing)

                         Circle()
                             .fill(Color.black.opacity(0.5))
                             .scaledToFit()
                            .frame(width: self.circleDiameter, height: self.circleDiameter)
                         scrollTopMarkerView.frame(height:0)
                         ScrollView(.horizontal) {
                             Text("The quick brown fox jumps over the lazy dog. Finally.")
                                 .font(Font.title)
                                .frame(width: self.scrollWidth, height: self.scrollHeight)
                                 .foregroundColor(Color.white)
                                 .background(Color.white.opacity(0.25))
                                 .background(scrollOffsetMarkerView)
                         }
                         .frame(width: viewGeometry.size.width, height: self.scrollHeight)
                         .padding([.top, .bottom], self.spacing)

                         Circle()
                             .fill(Color.white.opacity(0.5))
                             .scaledToFit()
                            .frame(width: self.circleDiameter, height: self.circleDiameter)

                        Spacer(minLength: self.spacing)
                     }
                     .frame(width: viewGeometry.size.width)
                 }
                 .background(Color.orange)
             }
             .frame(width: 324 / 2, height: spacing * 4 + circleDiameter * 2 + scrollHeight) // testing
             .cornerRadius(radius)
             .background(Color.black)
         }
}
Run Code Online (Sandbox Code Playgroud)