无需使用 LazyVStack 在 SwiftUI 上固定视图

PinnedScrollView

PinnedScrollView 是一个轻量级 SwiftUI 库,只需添加即可在滚动视图中固定任何视图,例如标题,而无需使用 LazyVStackSection

用法

var body: some View {
    ScrollView {
        VStack(spacing: 0) {
            ForEach(0..<20) { _ in
                Text("Header")
                    .pinned() // 1
                
                Text("Some content text")
            }
        }
    }
    .pinnedScrollView() // 2
}
  1. .pinned() 修饰符添加到想要在滚动视图中固定的视图
  2. .pinnedScrollView() 修饰符添加到相应的滚动视图

就是这样!

可选观察

如果想要在固定状态发生改变时收到通知,还可以向 pinned 修饰符提供可选闭包 onReachedTop: (Bool) -> ()

@State private var isHeaderReachedTop = false

// ...
Text("Header" + (isHeaderReachedTop ? " Reached" : ""))
    .pinned { isReachedTop in
        isHeaderReachedTop = isReachedTop
    }

限制

PinnedScrollView 需要 iOS/iPadOS 14.0。

PinnedScrollView 只支持垂直 ScrollView,不支持水平 ScrollViewList 视图。

安装

使用 Swift Package Manager 将 PinnedScrollView 添加到项目中。

https://github.com/Lumisilk/PinnedScrollView.git

许可证

此软件包在 MIT 开源许可证下获得许可。

灵感

PinnedScrollView 的实现灵感来自 objc.io 的课程 针对滚动视图的粘性标题。不同于 objc.io 使用 PreferenceKey 来协调标题的框架的初始实现,这可能导致性能瓶颈,PinnedScrollView 使用 onChange 来有效记录标题的框架。

此外,PinnedScrollView 使用 Combine 的 debounce 和发布者来最小化标题的正文的重新评估计数,旨在优化性能。

特别感谢 @auramagi 提供算法建议。

GitHub

点击跳转