
概述
在 SwiftUI 开发的应用中,往往在小屏设备(比如 iPhone)上布局良好的 App 放到大屏(iPad)上后就会"一塌糊涂"。因为它们一味的只想着"占据"却不知道"舍弃"。

从 iOS 17.0(iPad 17.0)开始苹果提供了原生的视图修改器方法专注于处理此事。
在本篇博文中,您将学到如下内容:
- "不和谐"的 iPad 内容空白
- 使用屏幕类别(Size Class)因地制宜
- iOS 17 新增的视图间隙调整方法
相信学完本课后,小伙伴们无论在何种尺寸屏幕上的 App 都会运行的恰如其分、悠然自得。
那还等什么呢?Let's fix it!!!;)
1. "不和谐"的 iPad 内容空白
下面是一段非常简单的 SwiftUI 代码,我们在视图中显示了一个包含 100 行内容的列表:
swift
struct ContentView: View {
var body: some View {
NavigationStack {
List {
ForEach(1..<100) { index in
Text("Item \(index)")
}
}
.font(.title)
.navigationTitle("Item list")
}
}
}
这在 iPhone 上表现的还算"中规中矩":

不过,如果在 iPad 上运行又会有怎样的结果呢?

可以看到:我们的 App 在大屏设备上并没有很好的把控"浩瀚无垠"的尺寸,它只是"单纯"的占据所有空间而已。
实际上,我们希望 App 在空间充足的情况下可以更加小巧紧凑,而不是一味"得寸进尺"的"索取"。
2. 使用屏幕类别(Size Class)因地制宜
在 SwiftUI 开发中,我们可以利用屏幕类别(Size Class)来检测当前运行设备屏幕的尺寸类型,然后根据需要因地制宜的调整对应的布局:

理想情况下我们可以在 iPhone 上保持布局不变,而在 iPad 上运行时"知趣的"为视图周边增加稍许横向空白:
swift
struct ContentView: View {
@Environment(\.horizontalSizeClass) private var sizeClass
var body: some View {
NavigationStack {
List {
ForEach(1..<100) { index in
Text("Item \(index)")
}
}
.font(.title)
.navigationTitle("Item list")
.safeAreaPadding(.horizontal, sizeClass == .regular ? 100 : 0)
}
}
}
运行代码,我们发现在 iPad 中 List 内容多了一些横向间隙,这样看起来显得更加安安合适啦!

不过用上面这种方法增加列表空白间隙的同时也会横向"压缩" List 滚动条的位置,这往往不是我们想要的结果。
别担心,我们可以轻而易举的搞定它!
3. iOS 17 新增的视图间隙调整方法
用 safeAreaPadding 修改器方法来增加横向间隙时会导致滚动条也参与到布局的"考量"之中。

有时,我们仅仅希望压缩视图内容而将滚动条的位置保持"原封不动"。幸运的是,从 iOS 17(iPad 17)开始苹果提供了全新的 contentMargins 修改器方法为我们分忧解难:

使用它我们可以非常方面的细粒度定制空白间隙的外观,比如我们可以选择间隙会影响哪些对象:
swift
struct ContentView: View {
@Environment(\.horizontalSizeClass) private var sizeClass
var body: some View {
NavigationStack {
List {
ForEach(1..<100) { index in
Text("Item \(index)")
}
}
.font(.title)
.navigationTitle("Item list")
.contentMargins(
.horizontal,
sizeClass == .regular ? 100 : 0,
for: .scrollContent
)
}
}
}
在上面的代码中,我们调用 contentMargins 方法并向其最后一个实参传入 .scrollContent 值,这表示我们对内容周边空间的"压缩"并不会影响滚动条的位置:

再次运行代码,现在 iPad 列表内容得到了完美的横向空白间隙,而且滚动条的位置仍然保持不变!棒棒哒!💯
总结
在本篇博文中,我们讨论了在 SwiftUI 中调整视图周边空白间隙从而让其在 iPhone 和 iPad 都表现得相当 nice 的方法,我们还进一步介绍了如何利用 iOS 17(iPad 17)里新增的方法让以上的实现更加锦上添花的"秘技"!
感谢观赏,再会!8-)