SwiftUI ScrollView ScrollTo 偏移(不是 ID)

问题描述 投票:0回答:1

是否可以在 SwiftUI 中设置 ScrollView 偏移量?

我制作了一个自定义选项卡栏,它使用 Switch/Case 来更改视图。然而,我的视图都包含垂直滚动视图。我知道每次我在视图之间切换时,它们都会被破坏,因此滚动视图偏移量就会丢失。

我已使用以下方法来获取 ScrollView Offset,但是我现在不确定如何使用此信息。我已经看到现在有 ScrollTo 但这似乎只适用于 ID。

是否可以以某种方式将 ScrollTo 与 Offset 一起使用?

一般来说,我想要实现的是标准选项卡栏行为,其中用户返回到他们离开每个选项卡的相同位置

如有任何帮助,我们将不胜感激。另外,请告诉我这是否对性能不利,因为我是新手。谢谢。

private struct ScrollViewOffsetPreferenceKey: PreferenceKey {
    static var defaultValue: CGPoint = .zero
    static func reduce(value: inout CGPoint, nextValue: () -> CGPoint) { }
}

struct ScrollViewWithOffset<T: View>: View {
    let axes: Axis.Set
    let showsIndicator: Bool
    let offsetChanged: (CGPoint) -> Void
    let content: T
    
    init(axes: Axis.Set = .vertical,
         showsIndicator: Bool = false,
         offsetChanged: @escaping (CGPoint) -> Void = { _ in },
         @ViewBuilder content: () -> T
    ) {
        self.axes = axes
        self.showsIndicator = showsIndicator
        self.offsetChanged = offsetChanged
        self.content = content()
    }
    
    var body: some View {
        ScrollView(axes, showsIndicators: showsIndicator) {
            GeometryReader { proxy in
                Color.clear.preference(
                    key: ScrollViewOffsetPreferenceKey.self,
                    value: proxy.frame(in: .named("scrollView")).origin
                )
            }
            .frame(width: 0, height: 0)
            content
        }
        .coordinateSpace(name: "scrollView")
        .onPreferenceChange(ScrollViewOffsetPreferenceKey.self, perform: offsetChanged)
    }
}

像这样使用...

ScrollViewWithOffset { point in
    scrollViewOffset = point.y
} content: {
    ScrollViewReader { proxy in
        LazyVStack(spacing: 4) {
            ForEach(0..<10, id: \.self) { i in
                Item()
                    .id(i)
            }
        }
    }
}
swiftui scrollview offset scrollto
1个回答
0
投票

iOS 18 将提供一个新的结构体

ScrollPosition

如果您的目标是 iOS 17 及更早版本,您可以使用 HStack 的偏移量或使用 Daniel Saidi 的想法,它使用 GeometryReader。

© www.soinside.com 2019 - 2024. All rights reserved.