在 NavigationStack 中为 List 添加边距同时保持滚动指示器到边缘 #
要在 NavigationStack
中的 List
上下添加间距,同时保持滚动指示器能够到达屏幕边缘,不能简单地使用 padding
,因为 padding
会作用于整个 List
容器,导致滚动指示器也被内缩。
正确解决方案 #
方法1:使用 listRowInsets
和 contentInset
#
NavigationStack {
List {
// 顶部间距 - 添加一个透明占位行
Color.clear
.frame(height: 10)
.listRowInsets(EdgeInsets())
.listRowSeparator(.hidden)
// 实际内容
ForEach(items) { item in
Text(item.name)
.listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
}
// 底部间距 - 添加一个透明占位行
Color.clear
.frame(height: 10)
.listRowInsets(EdgeInsets())
.listRowSeparator(.hidden)
}
.listStyle(.plain) // 使用plain样式确保效果一致
.scrollContentBackground(.hidden) // 隐藏默认背景
.scrollIndicators(.visible) // 确保滚动指示器可见
}
方法2:使用 safeAreaInset
(iOS 15+)
#
NavigationStack {
List {
ForEach(items) { item in
Text(item.name)
}
}
.safeAreaInset(edge: .top, spacing: 0) {
Color.clear.frame(height: 10)
}
.safeAreaInset(edge: .bottom, spacing: 0) {
Color.clear.frame(height: 10)
}
.listStyle(.plain)
}
方法3:使用 contentMargins
(iOS 17+)
#
如果你只支持 iOS 17+,可以使用新的 contentMargins
修饰符:
NavigationStack {
List {
ForEach(items) { item in
Text(item.name)
}
}
.contentMargins(.vertical, 10, for: .scrollContent)
.listStyle(.plain)
}
为什么这些方法有效? #
listRowInsets
方法:- 在列表顶部和底部添加透明行
- 设置
listRowInsets
为.zero
确保这些行不占用额外空间 - 滚动指示器仍然可以到达屏幕边缘
safeAreaInset
方法:- 在安全区域边缘添加间距
- 不影响滚动内容本身的布局
- 滚动指示器仍然可以到达边缘
contentMargins
方法 (iOS 17+):- 专门为这种场景设计
- 只影响内容,不影响滚动指示器
注意事项 #
- 避免使用
padding
,因为它会影响滚动指示器的位置 - 如果使用
listRowInsets
方法,记得隐藏分隔线 - 对于 iOS 16+,
scrollContentBackground(.hidden)
可以更好地控制背景 - 测试不同 iOS 版本,因为
List
的行为在不同版本间可能有差异
这些方法都能实现你想要的效果:列表内容有上下间距,但滚动指示器仍然可以到达屏幕边缘。