这个包提供了一个 ScrollView 的变体,你可以用它来追踪 ScrollView 内部的视图是否真正可见。
用法
var body: some View {
VisibilityTrackingScrollView(action: handleVisibilityChanged) {
LazyVStack {
ForEach(0..<100, id: \.self) { item in
Text("\(item)")
.trackVisibility(id: "\(item)")
}
}
}
}
func handleVisibilityChanged(_ id: String, change: VisibilityChange) {
switch change {
case .shown: print("\(id) shown")
case .hidden: print("\(id) hidden")
}
}
任何你想追踪的视图都应该应用 trackVisibility
修饰符。
当被追踪的视图滚动进入或离开容器的可视部分时,回调函数将被调用,并提供被追踪视图的 id 和新的状态。
你可以使用任何可哈希的类型作为传递给 .trackVisibility
的标识符,但它必须与回调函数使用的类型匹配(在上面的例子中,我们使用 String
标识符)。
如果你不小心在两个地方使用了不同的类型,这在编译时不会被检测到,因为它完全是有效的代码。然而,在运行时,trackVisiblity 修饰符将无法找到它期望的环境对象,并且你会得到一个崩溃。
在理想情况下,这本来是不必要的,因为 ScrollView 本身应该提供对这类功能的良好支持。
这个特殊的视图源于关于 SwiftUI 中不必要的刷新以及如何避免它们的讨论。
类似这样的技术在一个应用程序中使用过,但可能会导致对具有其他用途的环境对象的更改,从而导致更多严格来说不需要的刷新。
我建议尝试隔离这种行为,然后意识到我可能实际上可以将其打包成一个通用的视图/修饰符对。
它大量使用了 GeometryReader
,这并不理想,但实际上是我知道的唯一一种能及时工作的方法。
请查看 Extras 文件夹 中的示例项目。