SwiftUI — PinnedScrollableViews

SwiftUI 中,PinnedScrollableViews 是一个与 ScrollViewList 结合使用的功能,用于固定某些内容(通常是头部或分组标题)在滚动区域的顶部或其他特定位置。这个功能从 iOS 16 开始引入,为开发者提供了一种更灵活的滚动内容布局控制方式。


什么是 PinnedScrollableViews #

PinnedScrollableViewsScrollViewList 的一个选项,允许特定类型的滚动内容(如分组标题)在滚动时固定(Pinned)在视图的某个位置,例如顶部。

  • 常见场景:
    • 悬停的分组标题(Section Headers)。
    • 固定的导航条或工具栏。
    • 类似于 iOS 原生设置中的 “分区标题” 效果。

如何使用 PinnedScrollableViews #

PinnedScrollableViews 的类型为一个 Set,可以通过它指定哪些滚动元素可以被固定。SwiftUI 提供了两个内置值:

  • SectionHeaders:分组标题(Section Header)会在滚动时悬停在顶部。
  • SectionFooters:分组页脚(Section Footer)会类似地悬停。

语法 #

ScrollViewList 的配合使用:

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 的标题接替悬停效果,固定在顶部。

如果需要固定分组的页脚,可以使用 .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 1End 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 1Sticky Header 2 分别在滚动时悬停在顶部,具有自定义的样式。

PinnedScrollableViews 的属性细节 #

PinnedScrollableViews 是一个 Set 类型,可以包含多个选项:

  1. .sectionHeaders

    • 固定分组的头部(Section Header)。
    • 使用场景:让分组的标题悬停在顶部。
  2. .sectionFooters

    • 固定分组的页脚(Section Footer)。
    • 使用场景:在滚动时让分组的页脚悬停,例如显示汇总信息或操作按钮。

最佳使用场景 #

  1. 带分组的列表视图 (List):

    • 当数据通过分组组织时(如 iOS 设置界面、联系人列表分段),可以使用 .sectionHeaders 固定分组标题,方便上下文切换。
  2. 复杂滚动布局 (ScrollView + 自定义内容):

    • 比如实现自定义的头部导航栏黏性效果,或让某些重要信息(如快捷选项)在滚动中保持可见。
  3. 表格或汇总视图:

    • 可以在滚动时固定 .sectionFooters,用来显示汇总信息,不会因为滚动丢失焦点。
  4. 沉浸式 UI 设计:

    • 在使用大视差效果或复杂的导航布局时,可以通过 PinnedScrollableViews 让标题或页脚固定。

注意事项 #

  1. iOS 版本依赖

    • 仅支持 iOS 16+,在低版本设备上无法使用。
  2. 交互优化

    • 如果分组内容较少且不会触发滚动,PinnedScrollableViews 固定的效果可能不会触发。
    • 某些情况下可能需要额外的布局控制(如 LazyVStack),确保布局正确。
  3. 头部与页脚的粘性动画:

    • SwiftUI 会自动处理内容的 “接替悬停”,你无需额外代码调整。

总结 #

核心要点 #

  • PinnedScrollableViews 是一个 SwiftUI 提供的功能,用来在滚动视图中固定内容(分组头部或页脚)。
  • 其常用选项是 .sectionHeaders.sectionFooters,分别固定分组标题和页脚。
  • ListScrollView 配合使用,能够实现类似 iOS 设置界面的分组悬停体验。

何时使用? #

  1. 分组列表: 需要提升用户上下文信息的辨识度,比如分组数据展示。
  2. 复杂布局: 让某些重要的内容(如标题或快速操作)始终可见。
  3. 总结数据: 在滚动中固定分区的页脚以显示汇总或操作按钮。

通过 PinnedScrollableViews 的良好利用,可以轻松构建灵活的滚动布局,增强用户体验和界面设计的一致性。

本文共 1683 字,上次修改于 Jan 22, 2025