定位在 ZStack 内部
Positioning inside ZStack
我希望将这个红色矩形重新定位到左下角,但由于某些原因,我的对齐方式和填充没有按预期工作。我做错了什么以及如何将它移到左下角?
代码:
struct ContentView: View {
var body: some View {
ZStack {
VStack(spacing: 0) {
Rectangle()
.fill(Color.red)
.frame(width: 197, height: 163)
}
.frame(width: 284, height: 269)
.padding(.leading, 0)
.padding(.bottom, 0)
.background(Color.blue)
}
}
}
ZStack 有一个参数 alignment: Alignment
是
在两个轴上对齐。
struct ContentView: View {
var body: some View {
ZStack(alignment:.bottomLeading) {
Rectangle()
.fill(Color.blue)
.frame(width: 284, height: 269)
Rectangle()
.fill(Color.red)
.frame(width: 197, height: 163)
}
}
}
Yodagama 的答案可能是您想要的,但也值得探索您的困惑,因为 SwiftUI 布局并不像您想象的那样工作。像 .frame(...)
这样的调用不会“设置项目的大小”并且 .fill(...)
不会“设置项目的颜色”。 SwiftUI 中的几乎所有内容都会创建一个全新的 View,该 View 负责放置其 children。在许多情况下,它们看起来像是同一件事,但它们却大不相同。
我将分解您的代码中发生的事情,从内部开始并逐步解决。
Rectangle()
这将创建一个矩形,填充任何给定的 space。
Rectangle()
.fill(Color.blue)
这会将矩形嵌入到新视图中,将环境中的“填充”颜色设置为蓝色。
Rectangle()
.fill(Color.blue)
.frame(width: 197, height: 163)
这会将其嵌入到具有固定大小 (197x163) 的新视图中。嵌入的视图居中,但由于矩形占据了所有可用的space,它填充了框架。
VStack(spacing: 0) {
Rectangle()
.fill(Color.red)
.frame(width: 197, height: 163)
}
这会将 Frame 嵌入到 VStack 中,其元素之间没有间距(但这并不重要,因为只有一个)。 VStack 的大小恰好是其 children (197x163).
VStack(spacing: 0) {
Rectangle()
.fill(Color.red)
.frame(width: 197, height: 163)
}
.frame(width: 284, height: 269)
这会将 197x163 VStack 置于固定为 284x269 的新视图中。它不会 将 VStack 的大小设置为 284x269。 VStacks 总是恰好是它们 children 的大小。这是你出错的具体地方(我会在完成其余部分后解释如何修复它)。
VStack(spacing: 0) {
Rectangle()
.fill(Color.red)
.frame(width: 197, height: 163)
}
.frame(width: 284, height: 269)
.padding(.leading, 0)
.padding(.bottom, 0)
这将创建一个新视图,它嵌入了 284x269 帧,左侧有 0 个额外填充(因此这个新视图与当前帧的大小完全相同,这什么都不做)。然后它将其嵌入到一个新的视图中,该视图在底部添加了 0 个额外的填充。同样,这根本没有任何作用。
VStack(spacing: 0) {
Rectangle()
.fill(Color.red)
.frame(width: 197, height: 163)
}
.frame(width: 284, height: 269)
.padding(.leading, 0)
.padding(.bottom, 0)
.background(Color.blue)
这会将所有内容嵌入到一个新视图中,该视图绘制的蓝色背景与嵌入视图 (284x269) 的大小完全相同。
ZStack {
VStack(spacing: 0) {
Rectangle()
.fill(Color.red)
.frame(width: 197, height: 163)
}
.frame(width: 284, height: 269)
.padding(.leading, 0)
.padding(.bottom, 0)
.background(Color.blue)
}
}
最后,这会将所有内容集中在 ZStack 中。 ZStack 恰好是包装其 children 所需的大小,因此为 284x269。这根本没有任何作用。
那么你如何解决这个问题。您出错的地方是 VStack 在其周围框架中的定位方式。它居中,但您希望它对齐。这里不需要 ZStack,甚至不需要 VStack。你这样做:
Rectangle()
.fill(Color.red)
.frame(width: 197, height: 163)
.frame(width: 284, height: 269, alignment: .bottomLeading) // <===
.background(Color.blue)
注意两个框架视图是如何连续创建的。第一个边界矩形。第二个将其嵌入并对齐到更大的框架中。这是一个很好的例子,说明 SwiftUI 与开发人员想象的有何不同。事实上,这可以进一步简化,因为 Color 填充了它提供的所有 space,就像 Rectangle:
Color.red
.frame(width: 197, height: 163)
.frame(width: 284, height: 269, alignment: .bottomLeading)
.background(Color.blue)
但我经常发现在可能的情况下使用 Spacer 可以做得更好并且更灵活。根据我的经验,当您没有固定框架尺寸时,Spacers 会更好地工作。 (我并不是说这一定是最佳实践;这只是我的经验。SwiftUI 很新,我们仍在弄清楚什么是最佳实践。)
VStack {
Spacer() // Fill all space above
HStack {
Rectangle()
.fill(Color.red)
.frame(width: 197, height: 163)
Spacer() // Fill all space to the right
}
}
.frame(width: 284, height: 269)
.background(Color.blue)
我希望将这个红色矩形重新定位到左下角,但由于某些原因,我的对齐方式和填充没有按预期工作。我做错了什么以及如何将它移到左下角?
代码:
struct ContentView: View {
var body: some View {
ZStack {
VStack(spacing: 0) {
Rectangle()
.fill(Color.red)
.frame(width: 197, height: 163)
}
.frame(width: 284, height: 269)
.padding(.leading, 0)
.padding(.bottom, 0)
.background(Color.blue)
}
}
}
ZStack 有一个参数 alignment: Alignment
是
在两个轴上对齐。
struct ContentView: View {
var body: some View {
ZStack(alignment:.bottomLeading) {
Rectangle()
.fill(Color.blue)
.frame(width: 284, height: 269)
Rectangle()
.fill(Color.red)
.frame(width: 197, height: 163)
}
}
}
Yodagama 的答案可能是您想要的,但也值得探索您的困惑,因为 SwiftUI 布局并不像您想象的那样工作。像 .frame(...)
这样的调用不会“设置项目的大小”并且 .fill(...)
不会“设置项目的颜色”。 SwiftUI 中的几乎所有内容都会创建一个全新的 View,该 View 负责放置其 children。在许多情况下,它们看起来像是同一件事,但它们却大不相同。
我将分解您的代码中发生的事情,从内部开始并逐步解决。
Rectangle()
这将创建一个矩形,填充任何给定的 space。
Rectangle()
.fill(Color.blue)
这会将矩形嵌入到新视图中,将环境中的“填充”颜色设置为蓝色。
Rectangle()
.fill(Color.blue)
.frame(width: 197, height: 163)
这会将其嵌入到具有固定大小 (197x163) 的新视图中。嵌入的视图居中,但由于矩形占据了所有可用的space,它填充了框架。
VStack(spacing: 0) {
Rectangle()
.fill(Color.red)
.frame(width: 197, height: 163)
}
这会将 Frame 嵌入到 VStack 中,其元素之间没有间距(但这并不重要,因为只有一个)。 VStack 的大小恰好是其 children (197x163).
VStack(spacing: 0) {
Rectangle()
.fill(Color.red)
.frame(width: 197, height: 163)
}
.frame(width: 284, height: 269)
这会将 197x163 VStack 置于固定为 284x269 的新视图中。它不会 将 VStack 的大小设置为 284x269。 VStacks 总是恰好是它们 children 的大小。这是你出错的具体地方(我会在完成其余部分后解释如何修复它)。
VStack(spacing: 0) {
Rectangle()
.fill(Color.red)
.frame(width: 197, height: 163)
}
.frame(width: 284, height: 269)
.padding(.leading, 0)
.padding(.bottom, 0)
这将创建一个新视图,它嵌入了 284x269 帧,左侧有 0 个额外填充(因此这个新视图与当前帧的大小完全相同,这什么都不做)。然后它将其嵌入到一个新的视图中,该视图在底部添加了 0 个额外的填充。同样,这根本没有任何作用。
VStack(spacing: 0) {
Rectangle()
.fill(Color.red)
.frame(width: 197, height: 163)
}
.frame(width: 284, height: 269)
.padding(.leading, 0)
.padding(.bottom, 0)
.background(Color.blue)
这会将所有内容嵌入到一个新视图中,该视图绘制的蓝色背景与嵌入视图 (284x269) 的大小完全相同。
ZStack {
VStack(spacing: 0) {
Rectangle()
.fill(Color.red)
.frame(width: 197, height: 163)
}
.frame(width: 284, height: 269)
.padding(.leading, 0)
.padding(.bottom, 0)
.background(Color.blue)
}
}
最后,这会将所有内容集中在 ZStack 中。 ZStack 恰好是包装其 children 所需的大小,因此为 284x269。这根本没有任何作用。
那么你如何解决这个问题。您出错的地方是 VStack 在其周围框架中的定位方式。它居中,但您希望它对齐。这里不需要 ZStack,甚至不需要 VStack。你这样做:
Rectangle()
.fill(Color.red)
.frame(width: 197, height: 163)
.frame(width: 284, height: 269, alignment: .bottomLeading) // <===
.background(Color.blue)
注意两个框架视图是如何连续创建的。第一个边界矩形。第二个将其嵌入并对齐到更大的框架中。这是一个很好的例子,说明 SwiftUI 与开发人员想象的有何不同。事实上,这可以进一步简化,因为 Color 填充了它提供的所有 space,就像 Rectangle:
Color.red
.frame(width: 197, height: 163)
.frame(width: 284, height: 269, alignment: .bottomLeading)
.background(Color.blue)
但我经常发现在可能的情况下使用 Spacer 可以做得更好并且更灵活。根据我的经验,当您没有固定框架尺寸时,Spacers 会更好地工作。 (我并不是说这一定是最佳实践;这只是我的经验。SwiftUI 很新,我们仍在弄清楚什么是最佳实践。)
VStack {
Spacer() // Fill all space above
HStack {
Rectangle()
.fill(Color.red)
.frame(width: 197, height: 163)
Spacer() // Fill all space to the right
}
}
.frame(width: 284, height: 269)
.background(Color.blue)