Section 02 : Layout & Stacks - 布局和堆栈(22’28")
Build a custom UI from scratch using layout techniques and modifiers in SwiftUI.
在 SwiftUI 中使用布局技术和修饰器从头开始构建自定义UI。
【注】 **from scratch** 白手起家;从头做起
1. 复制 icons 到 Assets.xcassets
文件夹
(1)在 Project Navigator
中,选取Assets.xcassets
,然后选择 AppIcon
。
(2)在 Finder
中找到 项目文件夹\Assets\AppIcon
,使用 ⌘ + A
选中文件夹里面的所有文件。
(3)拖拽文件到 Xcode,按照尺寸将对应的图标设定好,暂时没法设定的,可以删除。
2. 复制图片等资源到 Assets.xcassets
文件夹
将 项目文件夹\Assets
中除去 AppIcon 文件夹之外的所有内容都拖拽到 Xcode 中,其中包含了若干图片和一个定义颜色的文件夹,修改这些图片和颜色定义,可以直接应用到 UI 中。有关具体使用将在后续章节中的相关部分中介绍。
3. 修改第一个文本框并增加修饰
(1)直接修改 Text 中双引号中的内容。
(2)在 Preview 中,按住 ⌘ 点击 Text,会弹出菜单,选择 Show SwiftUI Inspector...
后,将 Font
选择为 Title
,将 FontWeight
选择为 Bold
。可以看到代码区会自动增加了相关的修饰器的语句。
Font 修饰符可以使用
.font(.system(size: CGFloat))
方法直接指定字号。但是我在其他课程中发现,在 alert 提示框中似乎无效。
4. 增加一个新的文本框(Text)
(1)可以点代码区右上的 +
按钮,也可以用快捷键 “⌘ + ⇧ + F” 。在弹出的元素选择窗口中,在筛选框中输入关键字 “text”,选择 Text 控件。拖动到 Preview 窗口,可以放置在已有控件的任何一侧,现在将其放在下方。
元素选择窗口
- 顶部是查询栏,输入关键字可以筛选下面的列表
- 分类按钮从左到右依次为:控件、修饰器、代码片段、图片、颜色
- 左侧是筛选列表,点击选中某一项,右边会出现对应的文档。
代码区会自动生成有关 Text 控件的代码,而且还加上了 VStack
将两个控件包裹起来。(默认情况下,SwiftUI的每个元素都是居中的,这是为了保证在不同尺寸的屏幕上都可以适配显示。而类似 CSS 或者 Swift 则都是从左上角开始。这使得 SwiftUI 在修改控件位置时产生更少的代码。)
Stack
本质上有点像 CSS 里的弹性布局 flexbox。可以将元素加到一起,各个元素均匀分布并且相互对齐。SwiftUI 中共有三种 Stack,分别是:HStack(水平布局)、VStack(垂直布局)和 ZStack(层级布局)。
(2)为新的文本框选择修饰,这次选择 Color
。在弹出的选择列表中,不仅可以看见 SwiftUI 默认提供的一些颜色名称,还有 Assets.xcassets
中 color 文件夹下前面我们复制好的颜色名称。这里选择“accent”。可以看见在代码区再次自动增加了代码。
5. 修饰 VStack
在代码区中,按住 ⌘ 点击 VStack,同样会像在预览区那样弹出快捷菜单,将 Alignment 选择为左对齐。可以看见自动添加了代码,预览区也更新了显示。
【 Xcode Bug 】本次实验的过程中,这个动作出现了 bug,显示的 inspector 不完整。而在预览区的操作是没问题的。
第二遍看的时候,选择使用按住 ⌃ + ⌥ 点击,貌似正常了
6. 增加 logo 图片(Image)
使用快捷键 “⌘ + ⇧ + F” 打开窗口,选择图片,可以看到我们已经在 assets 中复制好的图片。拖拽 Logo1 到预览区,放置在 VStack 的右侧。可以看到代码区生成了图片控件的代码并将其与 VStack 一起用一个 HStack 包裹起来。
7. 修饰 HStack
可以在 VStack 和 logo 图片中间增加 Spacer 来撑开二者的间距。在 VStack 和图像控件之间加入一个空行,将光标放在空行内,呼出元素选择窗口,选中控件分类,找到并双击 Spacer控件。可以看见由于插入了 Spacer,VStack被顶到了左边,而logo图片则被顶到了右边,整个 HStack 就被撑满了。
8. 添加另一张图片
(1)呼出元素选择窗口,选择并拖拽图片 Card1 到 HStack 的下方。可以看到又生成了一个 VStack。
(2)同样的,我们在 HStack 和 Image 两个控件中插入一个 Spacer
,将新的 VStack 撑满。
(3)然后,给这个 VStack 加上一个大小的修饰 frame
,宽度 width
设为 340,高度 height
设为 220。
(4)这时我们可以看到图片太大了,超出了 VStack 的边界。所以给图片增加修饰器 resizable
来调整图片的大小。
(5)为了保持图片的宽高比,再给图片增加修饰器 aspectRatio
,选择 contentMode
的值为 .fit
。
这些操作完全可以直接在代码区直接键入。键入的过程中,Xcode 提供的自动完成功能可以给我们很好的提示,帮助我们快速完成代码。毕竟要记住如此众多的控件、修饰器和各种参数的名字还是挺费劲的。如:在aspectRatio 修饰器中,当键入 contentMode 后面的冒号之后,Xcode 就会给出 fit 和 fill 两个选择,使用上下箭头选中后按 Tab 键就可以了。
9. 修改整个卡片的外观
(1)使用 background
修饰器为卡片加上背景颜色,Color.blue
就是系统内置的蓝色。
(2)使用 cornerRadius
修饰器为卡片加上圆角修饰,设定圆角半径为 20 。
(3)使用 shadow
修饰器为卡片加上阴影修饰,设定阴影的半径为 20 。
10. 修饰内边距(padding)
由于使用了圆角修饰,被撑满的 HStack 中的文字被“削”掉了一块。为了能正确显示,我们可以在 HStack 上使用 padding
修饰。如果不给任何参数,内边距的四个方向都是 16,这个值已经可以符合大多数情况的需要了。但在这个例子中,我们只需要上、左、右三个方向。使用 .horizontal
增加左右边距,使用 .top
增加上边距。
同理,可以推测出,上下边距对应的 .vertical 以及其他三个方向单独的用法,.bottom,.left 和 .right 等。实际上,在代码区中,在 padding 后面的括号中键入 .
之后就可以看到 Xcode 给出的自动完成提示。这个操作我们也可以在修饰器窗口中实现。
11. 修改卡片的底色(Background)
(1)将整个卡片的背景色由蓝色改为黑色( .black
)。这里 SwiftUI 会推测你要键入的就是颜色,从而省略了前面的调用者 Color。这可以让代码更简洁。
(2)使用 foregroundColor
修饰器给 “UI Design” 文本框加上前景色白色( .white
)让文本能够被看见。
12. 修改背景图片
(1)将图片 Card1 中的 aspectRatio 修饰器的 contentMode 改为 .fill ,这时图片会变大。
(2)使用 frame 修饰器修改图片的大小。用快捷键呼出元素选择窗口,输入 frame 筛选,在修饰器分类中双击 frame 修饰器,在代码区可以看见新增的代码 .frame(width: 100.0, height: 100.0)
并且光标焦点停留在 width 后面的 100.0 上。直接输入宽度 300,按 Tab 键,光标自动跳到下一个参数 height 后的 100.0 上方便继续输入,输入高度 110。
(3)此时,由于图片的默认对齐为居中,所以占据了大部分卡片的区域。修改对齐的方式很简单,只需要在 height 的值后面加上 , alignment: .top
就可以了。
实际上,如果是在代码区直接键入 padding 修饰符,Xcode 给出的自动完成提示包括了 aligment。
到目前为止,针对单张卡片的工作基本上完成,但是我们没有研究如何在三维空间进行布局,比如在这张卡的后面再加一张卡,这就需要另一个尚未用到的布局控件—— ZStack。
13. 增加一张新的卡片
(1)在最外层的 VStack 上使用 ⌘ + click 呼出快捷菜单,选择 Embed in VStack
将其包裹在一个新的 VStack 中。
(2)将 VStack 修改为 ZStack。注意:Swift 是大小写敏感的!
(3)在当前卡片的 VStack 前面输入 Spacer 占位符,使用 ⌘ + click 快捷键在弹出菜单中选择 Embed in VStack
将其包裹在一个新的 VStack 中。这个新的 VStack 可以看做是另一张卡片。
(4)使用修饰器对新的 VStack 进行修饰。
VStack {
Spacer()
}
.frame(width: 300.0, height: 220.0)
.background(Color.blue)
.cornerRadius(20)
.shadow(radius: 20)
.offset(x: 0, y: -20)
以不同顺序应用 SwiftUI 修饰器会产生不同的效果。例如,如果先做阴影后定义圆角,则阴影效果会因为圆角效果的修剪(clipping)效果而失效。可以这样理解,每个修饰器都在修饰前面的视图(这个视图尚未或者已经带有修饰效果)。
从这段代码中,我们可以看见两个 VStack 都使用了差不多的修饰器内容。为了使代码更加简洁,我们可以尝试抽取一段专门用于卡片的代码,今后可以通过复用这段代码来创建更多的卡片。我们将在下一节讨论这个话题。
本节小结
所有的控件默认都是居中的。
增加元素的方法是呼出元素选择窗口(点击
+
按钮或者使用快捷键 “⌘ + ⇧ + F” ),拖拽控件、修饰器、图片等到代码区或者预览区,代码会自动生成。如果需要,会自动生成布局控件将其包裹。布局控件(Stack)有三类:HStack(水平布局)、VStack(垂直布局)和 ZStack(层级布局)。Spacer 控件可以用做占位符,将布局控件撑满。
预览区的所有的操作都可以通过直接在代码区键入代码完成。键入代码的过程中,Xcode 会有自动提示。
使用 ⌘ + click 可以呼出快捷菜单,可以干很多事情,这个快捷键使用频度非常非常高。
Swift 是大小写敏感的。
修饰器:前景色、背景色、字号、字体、圆角、偏移、内边距、阴影等修饰器的基本使用。
控件:Text、Image。
容器: VStack、HStack、ZStack。
接下来
尝试抽取代码