在 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)
            }
    }
}

解决方法

Yodagama 的答案可能是您想要的,但也值得探索您的困惑,因为 SwiftUI 布局并不像您想象的那样工作。像 .frame(...) 这样的调用不会“设置项目的大小”,.fill(...) 不会“设置项目的颜色”。 SwiftUI 中的几乎所有内容都创建了一个全新的 View,它负责放置其子项。在许多情况下,这些感觉就像是同一件事,但实际上却大不相同。

我将分解您的代码中发生的事情,从内部开始并逐步解决。

                Rectangle()

这会创建一个 Rectangle 来填充它给定的任何空间。

                Rectangle()
                    .fill(Color.blue)

这会将矩形嵌入到一个新视图中,该视图将环境中的“填充”颜色设置为蓝色。

                Rectangle()
                    .fill(Color.blue)
                    .frame(width: 197,height: 163)

这会将其嵌入到具有固定大小 (197x163) 的新视图中。嵌入的 View 居中,但由于 Rectangle 占用了所有可用空间,因此它填充了 Frame。

            VStack(spacing: 0) {
                Rectangle()
                    .fill(Color.red)
                    .frame(width: 197,height: 163)
            }

这会将该 Frame 嵌入到一个 VStack 中,该 VStack 在其元素之间没有间距(但这并不重要,因为只有一个)。 VStack 正好是它的孩子的大小 (197x163)。

            VStack(spacing: 0) {
                Rectangle()
                    .fill(Color.red)
                    .frame(width: 197,height: 163)
            }
            .frame(width: 284,height: 269)

这将 197x163 VStack 集中在一个固定为 284x269 的新视图中。它将 VStack 的大小设置为 284x269。 VStacks 总是正好是他们孩子的大小。这是您出错的具体地方(我将在完成其余部分后解释如何修复它)。

            VStack(spacing: 0) {
                Rectangle()
                    .fill(Color.red)
                    .frame(width: 197,height: 269)
            .padding(.leading,0)
            .padding(.bottom,0)

这将创建一个新视图,该视图嵌入了 284x269 帧,左侧有 0 个额外的填充(因此这个新视图与当前帧的大小完全相同,并且什么也不做)。然后将其嵌入到一个新的 View 中,在底部添加 0 个额外的填充。同样,这根本没有任何作用。

           VStack(spacing: 0) {
                Rectangle()
                    .fill(Color.red)
                    .frame(width: 197,0)
            .background(Color.blue)

这会将所有内容嵌入到一个新视图中,该视图绘制的蓝色背景与嵌入的视图 (284x269) 完全相同。

    ZStack {
            VStack(spacing: 0) {
                Rectangle()
                    .fill(Color.red)
                    .frame(width: 197,0)
            .background(Color.blue)
        }
}

最后,这一切都集中在 ZStack 中。 ZStack 正是包装其子项所需的大小,因此是 284x269。这根本没有任何作用。


那么你如何解决这个问题。您出错的地方是 VStack 在其周围 Frame 中的定位方式。它居中,但您希望它对齐。这里不需要 ZStack,甚至不需要 VStack。你这样做:

    Rectangle()
        .fill(Color.red)
        .frame(width: 197,height: 163)
        .frame(width: 284,height: 269,alignment: .bottomLeading) // <===
        .background(Color.blue)

注意两个框架视图是如何连续创建的。第一个边界矩形。第二个将其嵌入并对齐到更大的框架中。这是 SwiftUI 与开发人员想象的如此不同的一个很好的例子。事实上,这可以进一步简化,因为颜色填充了它提供的所有空间,就像矩形一样:

    Color.red
        .frame(width: 197,alignment: .bottomLeading)
        .background(Color.blue)

但我经常发现,如果可能,使用 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)
,

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)
            }
            
            
        }
    }

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...