
目录
[ZStack HStack 和 VStack](#ZStack HStack 和 VStack)
[对齐 aligment](#对齐 aligment)
[间距 spacing](#间距 spacing)
[填充 Spacer()](#填充 Spacer())
[实现背景色 遮罩](#实现背景色 遮罩)
ZStack HStack 和 VStack
这是最基本三种布局容器,分别是堆叠、横向和纵向,通过这三种布局的组合可以创造出任意复杂的界面布局。
布局的参数
对齐 aligment
默认对齐是居中,可以指定为top、bottom等多种方式。
间距 spacing
子视图之间的距离,显然对ZStack是没有意义的。
全面屏和安全区
前一篇已经介绍过edgesIgnoringSafeArea,忽略安全区将使视图铺满屏幕,可以对顶级布局设置,但是四角和摄像头区域是残缺的。
如果对子级视图设置忽略安全区,子级的大小计算会根据整个屏幕来算,可能会超出父级大小,这有一点难以理解。
示例
下面的示例组合了ZStack和HStack,使用了对齐、间距和忽略安全区:
Swift
struct SwiftUIViewStack: View {
let fontsize : CGFloat = 40
var body: some View {
ZStack(alignment: .top){
Image("pic2").resizable()
.aspectRatio(contentMode: .fill)
//.edgesIgnoringSafeArea(.all)
HStack(alignment: .bottom,spacing:80){
Image(systemName: "water.waves")
.font(.system(size: fontsize*2)).bold()
.foregroundStyle(.red)
Text("Hello").font(.system(size: fontsize)).bold()
.foregroundStyle(.red)
}//.edgesIgnoringSafeArea(.all)
}.edgesIgnoringSafeArea(.all)
}
}
效果:

填充 Spacer()
Spacer()视图用来填充空闲空间,可以替代对齐方式。比如顶部加一个Spacer()就会把其余部分挤到底部,相当于bottom对齐。
警告
视图可能会超出屏幕大小
如果图片比较大,同时又限制了纵横比,那么实际视图可能比屏幕大,这会导致父视图也变大,从而导致相关的兄弟视图基于大于屏幕的父视图绘制,可能造成不能显示的困惑(实际是位于屏幕之外)。
可以单独使用.resizable()来确认图像到底有多大,单独使用.resizable()会把图像缩小到父视图范围内。
下面的截图才是完整的图片:

ZStack的对齐是左下角对齐(bottomLeading),在之前的示例中,由于背景图片很宽,采用左下角对齐H Stack是显示不出来的(只需要修改ZStack参数即可观察效果)。然而左下角对齐跟父视图宽度有关系?还是很困惑啊。
实现背景色 遮罩
很多时候我们需要背景色,背景色一定需要用到ZStack,我们可以直接给顶级容器设置背景色,也可以使用渐变色视图来实现。
渐变色背景
实现渐变色背景需要使用Gradient,分三种,LinearGradient,RadialGradient,RoundedRectangle,多使用线性渐变。
使用方法很简单,如下代码所示:
Swift
import SwiftUI
let backgroundGradient = LinearGradient(
colors: [Color.red, Color.blue],
startPoint: .top, endPoint: .bottom)
struct SwiftUIViewStack: View {
let fontsize : CGFloat = 40
var body: some View {
ZStack{
backgroundGradient
ZStack(alignment: .bottomLeading){
Image("pic2").resizable()
HStack(alignment: .bottom,spacing:80){
Image(systemName: "water.waves")
.font(.system(size: fontsize*2)).bold()
.foregroundStyle(.red)
Text("Hello").font(.system(size: fontsize)).bold()
.foregroundStyle(.red)
}
}
.padding(200)
.border(.yellow,width: 10)//这个边框在屏幕最外围,符合预期
}
.edgesIgnoringSafeArea(.all)
.border(.black,width: 10)//顶级边框,注意位置并不符合预期
}
}
上面的代码定义了一个LinearGradient,从红到蓝,从顶部到底部,放在ZStack里面作为最下面的视图。效果:

注意边框的问题,由于在最顶级设置了忽略安全区,预期顶级和次级边框应该都在最外围,但是实际上最外围的边框(黑色)不在最外围。而且,所有边框都没有侧边,只有上下两边。
LinearGradient也可直接作为background的参数,比如给Text加上渐变色背景。
使用单色背景
直接使用background即可设置单色背景:
Swift
struct SwiftUIViewStack: View {
let fontsize : CGFloat = 40
var body: some View {
ZStack{
//backgroundGradient 去掉这个
ZStack(alignment: .bottomLeading){
Image("pic2").resizable()
HStack(alignment: .bottom,spacing:80){
Image(systemName: "water.waves")
.font(.system(size: fontsize*2)).bold()
.foregroundStyle(.red)
Text("Hello").font(.system(size: fontsize)).bold()
.foregroundStyle(.red)
}
}
.padding(200)
.border(.yellow,width: 10)
}
.background(.green) //增加这个
.edgesIgnoringSafeArea(.all)
.border(.black,width: 10)
}
}
与之前的代码相比去掉了渐变色对象,增加了.background(.green),效果:

除了背景色不一样没有别的区别。注意.backgroundStyle(.green)是无效的。
如果删除忽略安全区的代码,你会发现,背景色仍然是全屏的(使用渐变色对象并无此问题)!而黄色的内层边框消失(因为被外层边框覆盖),再删除外层边框,则黄色边框出现在原来黑色边框的位置(这是符合预期的),如下图所示。

(这里是文档结束)