在 SwiftUI 中,PinnedScrollableViews 是一个与 ScrollView 和 List 结合使用的功能,用于固定某些内容(通常是头部或分组标题)在滚动区域的顶部或其他特定位置。这个功能从 iOS 16 开始引入,为开发者提供了一种更灵活的滚动内容布局控制方式。
什么是 PinnedScrollableViews?#
PinnedScrollableViews 是 ScrollView 或 List 的一个选项,允许特定类型的滚动内容(如分组标题)在滚动时固定(Pinned)在视图的某个位置,例如顶部。
- 常见场景:
- 悬停的分组标题(Section Headers)。
- 固定的导航条或工具栏。
- 类似于 iOS 原生设置中的 “分区标题” 效果。
如何使用 PinnedScrollableViews?#
PinnedScrollableViews 的类型为一个 Set,可以通过它指定哪些滚动元素可以被固定。SwiftUI 提供了两个内置值:
SectionHeaders:分组标题(Section Header)会在滚动时悬停在顶部。SectionFooters:分组页脚(Section Footer)会类似地悬停。
语法#
与 ScrollView 和 List 的配合使用:
ScrollView(.vertical) {
// 内容
}
.pinnedScrollableViews([.sectionHeaders, .sectionFooters]) // 指定固定规则或者:
List {
// 内容
}
.pinnedScrollableViews([.sectionHeaders]) // 仅固定分组标题示例 1:在 List 中固定分组标题#
最常见的用法是在 List 的分组结构中让分组标题 Section Header 固定在滚动视图顶部。
import SwiftUI
struct PinnedSectionHeaderExample: View {
var body: some View {
List {
Section(header: Text("Group 1").font(.headline)) {
ForEach(0..<10) { index in
Text("Item \(index)")
}
}
Section(header: Text("Group 2").font(.headline)) {
ForEach(10..<20) { index in
Text("Item \(index)")
}
}
}
.pinnedScrollableViews([.sectionHeaders]) // 固定分组标题
}
}效果:#
- 当用户向上滚动时:
Group 1的标题会悬停在视图顶部,直到Group 2的内容到达。Group 2的标题接替悬停效果,固定在顶部。
示例 2:自定义分组页脚 Section Footer#
如果需要固定分组的页脚,可以使用 .sectionFooters。
import SwiftUI
struct PinnedFooterExample: View {
var body: some View {
List {
Section(
footer: Text("End of Group 1").font(.caption)
) {
ForEach(0..<10) { index in
Text("Item \(index)")
}
}
Section(
footer: Text("End of Group 2").font(.caption)
) {
ForEach(10..<20) { index in
Text("Item \(index)")
}
}
}
.pinnedScrollableViews([.sectionFooters]) // 固定分组页脚
}
}效果:#
- 当用户滚动时,
End of Group 1或End of Group 2作为页脚悬停在视图的底部。
示例 3:在 ScrollView 中嵌套自定义内容#
你可以在 ScrollView 中自定义布局并使用 PinnedScrollableViews。
import SwiftUI
struct ScrollPinnedExample: View {
var body: some View {
ScrollView {
LazyVStack(pinnedViews: [.sectionHeaders]) {
Section(header: Text("Sticky Header 1")
.font(.headline)
.frame(maxWidth: .infinity)
.padding()
.background(Color.blue)) {
ForEach(0..<10) { index in
Text("Item \(index)")
.padding()
}
}
Section(header: Text("Sticky Header 2")
.font(.headline)
.frame(maxWidth: .infinity)
.padding()
.background(Color.green)) {
ForEach(10..<20) { index in
Text("Item \(index)")
.padding()
}
}
}
}
.pinnedScrollableViews([.sectionHeaders]) // 固定自定义分区头部
}
}效果:#
Sticky Header 1和Sticky Header 2分别在滚动时悬停在顶部,具有自定义的样式。
PinnedScrollableViews 的属性细节#
PinnedScrollableViews 是一个 Set 类型,可以包含多个选项:
.sectionHeaders:- 固定分组的头部(Section Header)。
- 使用场景:让分组的标题悬停在顶部。
.sectionFooters:- 固定分组的页脚(Section Footer)。
- 使用场景:在滚动时让分组的页脚悬停,例如显示汇总信息或操作按钮。
最佳使用场景#
带分组的列表视图 (
List):- 当数据通过分组组织时(如 iOS 设置界面、联系人列表分段),可以使用
.sectionHeaders固定分组标题,方便上下文切换。
- 当数据通过分组组织时(如 iOS 设置界面、联系人列表分段),可以使用
复杂滚动布局 (
ScrollView+ 自定义内容):- 比如实现自定义的头部导航栏黏性效果,或让某些重要信息(如快捷选项)在滚动中保持可见。
表格或汇总视图:
- 可以在滚动时固定
.sectionFooters,用来显示汇总信息,不会因为滚动丢失焦点。
- 可以在滚动时固定
沉浸式 UI 设计:
- 在使用大视差效果或复杂的导航布局时,可以通过
PinnedScrollableViews让标题或页脚固定。
- 在使用大视差效果或复杂的导航布局时,可以通过
注意事项#
iOS 版本依赖:
- 仅支持 iOS 16+,在低版本设备上无法使用。
交互优化:
- 如果分组内容较少且不会触发滚动,
PinnedScrollableViews固定的效果可能不会触发。 - 某些情况下可能需要额外的布局控制(如
LazyVStack),确保布局正确。
- 如果分组内容较少且不会触发滚动,
头部与页脚的粘性动画:
- SwiftUI 会自动处理内容的 “接替悬停”,你无需额外代码调整。
总结#
核心要点#
PinnedScrollableViews是一个 SwiftUI 提供的功能,用来在滚动视图中固定内容(分组头部或页脚)。- 其常用选项是
.sectionHeaders和.sectionFooters,分别固定分组标题和页脚。 - 与
List和ScrollView配合使用,能够实现类似 iOS 设置界面的分组悬停体验。
何时使用?#
- 分组列表: 需要提升用户上下文信息的辨识度,比如分组数据展示。
- 复杂布局: 让某些重要的内容(如标题或快速操作)始终可见。
- 总结数据: 在滚动中固定分区的页脚以显示汇总或操作按钮。
通过 PinnedScrollableViews 的良好利用,可以轻松构建灵活的滚动布局,增强用户体验和界面设计的一致性。