合作机构:阿里云 / 腾讯云 / 亚马逊云 / DreamHost / NameSilo / INWX / GODADDY / 百度统计
今年 SwiftUI? 新增最好的功能之一必须是布局协议。它不但让我们参与到布局过程中,而且也给了我们一个很好的机会去更好的理解布局在 SwiftUI 中的作用。
早在2019年,我写了一篇文章SwiftUI 中 frame 的表现[1],其中,我阐述了父视图和子视图如何协调形成最终视图效果。那里描述的许多情况需要通过观察不同测试的结果去猜测。整个过程就像是发现外星行星,天文学家发现太阳亮度微小的减少,然后推断出这一定是行星过境(了解行星过境[2])。
现在,有了布局协议,就像用自己的眼睛在遥远的太阳系漫游,令人振奋。
创建一个基础布局并不难,只需要实现两个方法。尽管如此,我们仍然有很多选择去实现一个复杂的容器。我们将会探索常规布局案例之外的内容。有许多有趣的话题到目前为止我还没有在任何地方看到过解释,所以我将在这里介绍它们。然而,在深入这些领域之前,我们需要先打下扎实的基础。
由于涉及到许多内容,我将分成两个部分:
如果你已经熟悉布局协议,你可能想直接跳到第二部分。这是可以的,尽管我仍然推荐你浏览第一部分,至少浅读一下。这将确保我们在开始探索第二部分中描述的更多高级特性时,我们在同一进度。
如果在阅读本文的任何时候,你认为布局协议不适合你(至少目前来说),我仍然建议你查看 Part2 的这一小节—一个有用的调试工具,这个工具可以帮助你使用 SwiftUI ,且不需要理解布局协议就可以使用。我将它放在第二部分结尾是有原因的,这个工具是使用本文的知识构建的。不过,你可以直接复制代码使用它。
采用布局协议类型的任务,是告诉 SwiftUI 如何放置一组视图,需要多少空间。这类型常常被作为视图容器,虽然布局协议是今年新推出的(至少公开来说),但是我们在第一天使用 SwiftUI 的时候就在使用了,当每次使用 HStack? 或者 VStack 放置视图时都是如此。
请注意至少到现在,布局协议不能创建懒加载容器,比如 LazyHStack? 或 LazyVStack。懒加载容器是指那些只在滚入屏幕时渲染,滚出到屏幕外就停止渲染的视图。
一个重要的知识点,Layout? 类型不是视图 。例如,它们没有视图拥有的 body 属性。但是不用担心,目前为止你可以认为它们就是视图并且像视图一样使用它们。这个框架使用了漂亮的 Swift? 语言技巧使你的布局代码在向 SwiftUI 中插入时产生一个透明视图 。我将在后面-高明的伪装者部分说明。
在我们开始布局代码之前,让我们重新审视一下 SwiftUI 框架的核心。就像我在以前的文章 SwiftUI 中 frame 的表现 所描述的的那样,在布局过程中,父视图给子视图提供一个尺寸,但最终还是由子视图决定如何绘制自己。然后,它将此传达给父视图,以便采取相应的动作。有三个可能的情况,我们将专注讨论于横轴(宽度),但纵轴(高度)同理:
情况一:如果子视图需求小于提供的视图
在这个例子中考虑文本视图,提供了比需要绘制文字更多的空间
struct ContentView: View {
var body: some View {
HStack(spacing: 0) {
Rectangle().fill(.green)
Text("Hello World!")
Rectangle().fill(.green)
}
.padding(20)
}
}
TOP