SwiftUI 调整视图内容周围间隙(Content Margins)的“时髦”方法

概述

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

从 iOS 17.0(iPad 17.0)开始苹果提供了原生的视图修改器方法专注于处理此事。

在本篇博文中,您将学到如下内容:

  1. "不和谐"的 iPad 内容空白
  2. 使用屏幕类别(Size Class)因地制宜
  3. 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-)

相关推荐
大熊猫侯佩13 小时前
Swift 初学者秘技:如何用模块(Module)进一步细粒度控制代码访问控制
swift·apple
iOS阿玮14 小时前
苹果审核被拒,其实可以靠回复也能过审
uni-app·app·apple
Eden小峰14 小时前
ReactiveSwift 核心操作符
swift
大熊猫侯佩14 小时前
Swift 5.9 中 if 与 switch 语句简洁新语法让撸码更带劲
swift·编程语言·apple
I烟雨云渊T2 天前
iOS swiftUI的实用举例
ios·swiftui·swift
大熊猫侯佩2 天前
SwiftUI 中为何 DisclosureGroup 视图在收缩时没有动画效果?
swiftui·swift·apple
大熊猫侯佩2 天前
Swift 初学者交心:在 Array 和 Set 之间我们该如何抉择?
数据结构·性能优化·swift
大熊猫侯佩3 天前
Swift 中更现代化的调试日志系统趣谈(一)
debug·swift·apple