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-)

相关推荐
kkoral8 小时前
基于MS-Swift 为 Qwen3-0.6B-Base 模型搭建可直接调用的 API 服务
python·conda·fastapi·swift
Yorelee.1 天前
ms-swift在训练时遇到的部分问题及解决方案
开发语言·nlp·transformer·swift
崽崽长肉肉2 天前
swift中的知识总结(一)
ios·swift
Yakamoz2 天前
Swift Array的写时复制
swift
汉秋2 天前
SwiftUI 中的 compositingGroup():真正含义与渲染原理
swiftui·swift
汉秋2 天前
SwiftUI 中的 @ViewBuilder 全面解析
swiftui·swift
iOS阿玮3 天前
1V1 社交精准收割 3.6 亿!40 款马甲包 + 国内社交难度堪比史诗级!
uni-app·app·apple
胖虎13 天前
SwiftUI 页面作为一级页面数据被重置问题分析
ios·swiftui·swift·state·observedobject·stateobject·swiftui页面生命周期
guangzan3 天前
AI 结队编程:解决 SwiftUI 窗口点击关闭按钮崩溃问题
swiftui·tca
健了个平_243 天前
【iOS】如何在 iOS 26 的UITabBarController中使用自定义TabBar
ios·swift·wwdc