截至6月22日,这已包含在 SwiftUI 2 测试版中。https://developer.apple.com/documentation/swiftui/scrollviewproxy
苹果实现只使用 .id(_:)
,我与此有一些更新问题,其中具有 ID 的视图有时在其 ObservedObject 发生变化时不会更新。也许这在新 SwiftUI 2 测试版中已得到修复。
此外,苹果实现仅支持 iOS 14,因此我认为此存储库对向后兼容仍然很有用。
ScrollViewProxy
添加 ScrollViewReader
和 ScrollViewProxy
,帮助您在 ScrollView 中滚动到特定位置
要获取 ScrollViewProxy,您可以使用 ScrollView 的便捷初始化方法
ScrollView { proxy in
...
}
或将 ScrollViewReader 添加到任何在底层创建 UIScrollView 的 View
List {
ScrollViewReader { proxy in
...
}
}
ScrollViewProxy 当前有一个变量和两个您可以调用的函数
/// A publisher that publishes changes to the scroll views offset
public var offset: OffsetPublisher
/// Scrolls to an edge or corner
public func scrollTo(_ alignment: Alignment, animated: Bool = true)
/// Scrolls the view with ID to an edge or corner
public func scrollTo(_ id: ID, alignment: Alignment = .top, animated: Bool = true)
要使用滚动到 ID 的函数,您必须将 ID 添加到您想要滚动的视图
ScrollView { proxy in
HStack { ... }
.scrollId("someId")
}
这是与 SwiftUI 2.0 实现不同的唯一部分,因为我不知道如何从 .id(_:)
函数访问具有 ID 的视图
示例
将所有内容汇集在一个示例中
struct ScrollViewProxyExample: View {
@State var randomInt = Int.random(in: 0..<200)
@State var proxy: ScrollViewProxy? = nil
@State var offset: CGPoint = .zero
var body: some View {
// GeometryReader for safeAreaInsets on Sticky View
GeometryReader { geometry in
VStack {
ScrollView { proxy in
Text("Sticky View")
.background(Color.white)
.onReceive(proxy.offset) { self.offset = $0 }
.offset(x: offset.x, y: offset.y + geometry.safeAreaInsets.top)
.zIndex(1)
VStack(spacing: 20) {
ForEach(0..<200) { index in
HStack {
Spacer()
Text("Item: \(index)").font(.title)
Spacer()
}.scrollId(index)
}
}
.zIndex(0)
.onAppear {
self.proxy = proxy
}
}
HStack {
Button(action: {
self.proxy?.scrollTo(self.randomInt, alignment: .center)
self.randomInt = Int.random(in: 0..<200)
}, label: {
Text("Go to \(self.randomInt)")
})
Spacer()
Button(action: { self.proxy?.scrollTo(.bottom) }, label: {
Text("Bottom")
})
Spacer()
Button(action: { self.proxy?.scrollTo(.center) }, label: {
Text("Center")
})
}.padding()
}
}
}
}
解耦
想要放弃对 iOS 13 的支持并迁移到 SwiftUI 2.0 版本吗?
- 移除包
- 添加此扩展
extension View {
public func scrollId<ID: Hashable>(_ id: ID) -> some View {
id(id)
}
}
(或将所有 .scrollId 替换为 .id)