2024-10-23 18:29:51
,某些文章具有时效性,若有错误或已失效,请在下方留言。叶子视图
这里是指没有子视图的视图。
Text
默认情况下,Text
视图会去适应任意的建议尺⼨,设法让⾃⼰适配 (不超过) 这个尺⼨。Text
使用的策略顺序如下:
- 将⽂本分成多⾏ (英⽂内容按单词换⾏)
- 单词内换⾏ (使⽤连词符号)
- 截断⽂本
- 裁剪⽂本
Text
始终会返回它所需要渲染的内容的大小,这个尺寸在宽度上一定小于或等于建议的跨度,在高度上除非提议的是 0x0
,否则至少是一行的高度。也就是说,Text
的宽度可以从零到完整渲染内容所需的宽度之间的任意值。
Text(“Hello, World!”) 在不同建议尺⼨下的渲染示例。虚线矩形代表建议尺⼨,实线矩形代表报告的尺⼨:

在 Text 上,我们可以使⽤⼀系列修饰符来改变它的⾏为:
.lineLimit(_ number:)
允许我们指定渲染时的最⼤⾏数,不论在建议尺⼨的垂直⽅向上空间⾜够与否,⽂本都不能超过这个⾏数。指定为nil
代表没有⾏数限制。.lineLimit(_ limit:reservesSpace:)
允许我们指定渲染时的最⼤⾏数,并且让我们有机会选择是否要在建议尺⼨⾜够的情况下,让额外的空格去将⾏数补充到这个最⼤⾏数。.truncationMode(_ mode:)
允许我们指定⽂本截断应该发⽣的位置。.minimumScaleFactor(_ factor:)
允许我们指定 Text 在需要缩⼩字体以适应建议尺⼨时,所能够使⽤的最⼩⽐例。
如果我们将 .fixedSize()
应⽤于 Text
,它将使⽤理想尺⼨,因为 .fixedSize()
向 Text
所建议的尺⼨是 nil⨉nil
。Text
的理想尺⼨是在不换⾏和不截断的情况下呈
现内容所需的尺⼨。下⾯是 Text("Hello, World!”).fixedSize()
在不同建议尺⼨下的渲染情况:

fixedSize
修饰符会确保⼦视图 (这⾥的 Text) 始终以其理想尺⼨进⾏渲染,⽽不考虑建议尺⼨。
决定视图布局的6 个值:
- 最小宽度和最小高度,用于存储该视图可接受的最小空间。任何小于这些值的内容都会被忽略,导致视图 “泄漏” 出建议给它的空间。
- 最大宽度和最大高度,用于存储视图可接受的最大空间。大于这些值的内容将被忽略,这意味着父视图必须在剩余空间内以某种方式定位视图。
- 理想宽度和理想高度,用于存储该视图所需的首选空间。只要这些值仍在最小值到最大值的范围内,就可以提供这些值之外的值。
形状
内置形状
⼤部分内置的形状类型 (Rectangle
,RoundedRectangle
,Capsule
,以及 Ellipse
) 接受从零到⽆限的任意⼤⼩的建议尺⼨,并且会填充所有可⽤空间。Circle
是⼀个特例:它会按照建议尺⼨的短边作为直径进⾏适配,然后将圆形的实际尺⼨进⾏汇报。
如果我们使⽤ nil
来对形状进⾏尺⼨建议 (⽐如,我们把形状包装到 fixedSize
⾥),它将使⽤ 10⨉10 这个默认尺⼨。
HStack {
Rectangle()
.fill(.orange)
.fixedSize()
Circle()
.fill(.red)
.fixedSize()
RoundedRectangle(cornerRadius: 4)
.fill(.yellow)
.fixedSize()
Capsule()
.fill(.yellow)
.fixedSize()
}

自定义形状
自定义书签形状的代码,如下所示
extension CGRect {
subscript(_ point: UnitPoint) -> CGPoint {
CGPoint(x: minX + width * point.x, y: minY + height * point.y)
}
}
struct BookmarkShape: Shape {
nonisolated func path(in rect: CGRect) -> Path {
Path { p in
p.move(to: rect[.topLeading])
p.addLines([
rect[.bottomLeading],
rect[.init(x: 0.5, y: 0.8)],
rect[.bottomTrailing],
rect[.topTrailing],
rect[.topLeading]
])
p.closeSubpath()
}
}
}
//struct BookmarkShape: Shape {
// nonisolated func path(in rect: CGRect) -> Path {
// Path { p in
// p.move(to: CGPoint(x: rect.minX, y: rect.minY))
// p.addLines([
// CGPoint(x: rect.minX, y: rect.maxY),
// CGPoint(x: rect.midX, y: rect.maxY * 0.8),
// CGPoint(x: rect.maxX, y: rect.maxY),
// CGPoint(x: rect.maxX, y: rect.minY),
// CGPoint(x: rect.minX, y: rect.minY)
// ])
//
// p.closeSubpath()
// }
// }
//}
struct Bookmark: View {
var body: some View {
VStack {
BookmarkShape()
.stroke(.red.gradient)
}
.padding()
}
}
自定义的形状也会填充所有可用的空间。

假设这个形状应该始终以 2⨉3 的宽⾼⽐进⾏渲染,可以在使⽤这个形状的地⽅添加上.aspectRatio
修饰符,也可以覆盖原有的 sizeThatFits 方法,返回需要的提议尺寸。
nonisolated func sizeThatFits(_ proposal: ProposedViewSize) -> CGSize {
var result = proposal.replacingUnspecifiedDimensions()
let ratio: CGFloat = 2 / 3
let newWidth = ratio * result.height
if newWidth <= result.width {
result.width = newWidth
} else {
result.height = result.width / ratio
}
return result
}

建议尺⼨的⾥的属性可能是 nil,因此我们⾸先要调⽤ replacingUnspeci!edDimensions 来获取⼀个 CGSize。然后,我们计算形状的宽度和⾼度,使其宽⾼⽐为 2×3,并适配到建议尺⼨中去。

颜色
当直接将颜⾊当作视图使⽤时,⽐如 Color.red
,从视图布局的视⻆来看,它的⾏为和 Rectangle().fill(.red)
是⼀样的。

图片
默认的情况下,Image
视图会报告一个固定值:也就是它所持有的图⽚的尺⼨。
在 Image
上调⽤ .resizable()
,这个视图就会完全灵活可变: Image
将会接受任意的建议尺⼨,并将它报告回去,同时将图像压缩或者拉伸到这个尺⼨。
在实践中,实际上任何⼀个 resizable
的图⽚都会
和 .aspectRatio(contentMode:)
或 .scaleToFit()
修饰器⼀同使⽤,以避免图⽚产⽣变形。
分割线
在⽔平堆栈 (⽐如 HStack
) 外使⽤ Divider
时,它接受任意的建议宽度,并将分隔线⾃身的默认⾼度进⾏汇报。
在⽔平堆栈内部使⽤时,分隔线会接受建议的⾼度,并报告分隔线的宽度。如果建议值是 nil
,那么它将根据所处环境,在可变轴上使⽤默认尺⼨ 10
。
VStack {
Spacer()
VStack {
// 在⽔平堆栈外使⽤ Divider
HStack {
Text("Divider outside of HStack")
}
Divider()
}
.padding()
.border(.green.gradient)
Spacer()
// 在⽔平堆栈内使⽤ Divider
VStack {
HStack {
Text("Divider inside of HStack")
Divider()
}
}
.padding()
.border(.green.gradient)
Spacer()
// 在⽔平堆栈外使⽤ Divider,且建议值为 nil
VStack {
Text("Divider outside of HStack with nil proposal")
Divider()
.fixedSize()
.background(.red.gradient)
}
.padding()
.border(.green.gradient)
Spacer()
// 在⽔平堆栈内使⽤ Divider,且建议值为 nil
VStack {
HStack {
Text("Divider inside of HStack with nil proposal")
Divider()
.fixedSize()
.background(.red.gradient)
}
}
.padding()
.border(.green.gradient)
}

Spacer
在⽔平堆栈和垂直堆栈之外,Spacer
接受从最⼩⻓度到⽆限⼤的所有建议尺⼨。
在垂直堆栈中,Spacer
接受从其最⼩⻓度到⽆限⼤的任何⾼度,但报告的宽度为零。在⽔平堆栈中,它的⾏为相同 (只是轴互换)。除⾮使⽤ Spacer
初始化⽅法中的 minLength
参数指定⼀个⻓度,否则 Spacer
的最⼩⻓度会是默认填充 (padding
) 的⻓度
暂无评论内容