在 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
的良好利用,可以轻松构建灵活的滚动布局,增强用户体验和界面设计的一致性。