要告诉 ZStack 在其中以特定方式对齐事物,请使用 alignment 参数对其进行配置:
ZStack(alignment: .top) {
Color.clear
Image(...)
Text("Hello, World!")
}
(Color.clear 扩展以填充所有可用空间,因此这会强制您的 ZStack 与封闭视图一样大,而无需添加 .frame()。)
当然,这会将所有内容对齐在顶部,这可能不是您想要的。你可以通过嵌套你的 ZStack 来解决这个问题:
ZStack{
ZStack(alignment: .top) {
Color.clear
Image(...) // This will be at the top
}
Text("Hello, World!") // This will be centered
}
也就是说,我可能会在此示例中使用.background。
ZStack {
Color.clear
Text("Hello, World!")
}
.background(Image(...), alignment: .top)
如果你只有一个视图,你可以去掉 ZStack 并使用框架:
Text("Hello, World!")
.frame(maxHeight: .infinity)
.background(Image(uiImage:#imageLiteral(resourceName: "image.jpg")),
alignment: .top)
请记住,在这种情况下,图像将绘制在其框架之外。在许多情况下这很好(而且它完全合法),但有时它可能很重要(例如,如果你把它放在一个堆栈中)。您可以在末尾添加.border(Color.green) 以查看其工作原理。
这个示例真正触及了 SwiftUI 布局的核心,因此值得了解发生了什么。这不是解决方法或技巧,所以你应该去感觉很正常的地方。
顶级内容视图(包含 ZStack 的视图)将其整个空间提供给 ZStack。 ZStack 的大小始终与包含其内容的大小完全相同,因此首先 ZStack 需要对其子项进行布局。它根据对齐方式对它们进行布局,然后精确调整自身大小以适应它们。因此,使用顶部对齐(但没有 Color.clear),图像位于 ZStack 的顶部。 ZStack 与 Image 的大小完全相同。
然后,顶级内容视图将 ZStack 置于其中心。
ZStack 布置其子项的方式与内容视图的方式类似。它提供了它所提供的所有空间,然后子视图决定它们的大小。 视图始终决定自己的大小。 Image 和 Text 是固定大小的视图,因此它们只是其内容的大小。但是 Color 是一个灵活大小的视图。它接受 ZStack 提供的整个空间(与顶级内容视图提供的空间相同)并将其作为其大小返回。由于 ZStack 必须准确地包含其子项,因此 ZStack 现在是顶级内容视图的大小,并且事情的行为与您预期的一样,在屏幕顶部对齐。
让我们与您最初使用.frame() 进行比较:
ZStack {
Image("bgImage")
Text("Hello, World!")
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.red) //this is for debugging purposes, to show the area of the ZStack
首先,我想重点关注您的评论,因为它不正确。这不是 ZStack 的区域。 ZStack 正是其内容(图像和文本)的大小。你把背景放在框架视图上,框架视图就大了。
人们的一个主要困惑是他们认为.frame(...) 改变了它所附加的视图的大小。这根本不正确。和以前一样,ZStack 始终是其内容的大小。 .frame() 创建一个请求大小的全新视图。然后它根据框架的对齐方式将包裹的视图定位在自身内部。所以在这个例子中它是这样工作的:
顶层 - 背景 - 框架 - ZStack - {图像文本}
顶层视图将其所有空间提供给背景。背景是它们所包含内容的大小,因此它为框架提供了所有空间。 Frame 在两个方向上都是灵活的(由于 max 字段),因此它会忽略其子项的大小并选择提供给它的大小。
Frame 然后将所有空间提供给 ZStack。 ZStack 布置其子级,并返回其大小与包含它们的大小完全相同。
Frame 然后根据 Frame 的对齐方式放置 ZStack(.center,因为这是默认设置)。如果您将 Frame 的对齐方式设置为 .top,那么 ZStack 将被放置在框架的顶部(但文本将在 ZStack 中而不是在 Frame 中居中)。
然后它向后台报告它与顶级视图一样大(因为它很灵活)。
背景然后声明与顶级内容视图相同的大小。
最后,顶级内容视图将背景置于其中心。