Spacer 不与 VStack 中的 Form 一起工作

Spacer not working with Form inside a VStack

我正在尝试在 TabBar 正上方的下方创建一个圆圈,表单内容位于下方。我可以通过使用 .frame() 来强制执行此操作,但我不太喜欢它。看起来应该有一个更简单的方法来将它对齐到底部。

我的理解是Spacer()应该把表格推到底部,把圆圈留在顶部,但似乎不是这样。

var body: some View {
    VStack {
        Circle().foregroundColor(.yellow).overlay(VStack {
            Text("Example")
        }).foregroundColor(.primary)
        
        Spacer()
        
        Form {
            TextField("test", text: $a)
            TextField("test2", text: $b)
        }
    }
}

Forms,如 Lists,展开以获取父视图中所有可用的 space。如果您将模拟器切换到 Light 模式,您将在 TextFields 后面看到一个浅灰色区域。那是你的表格。

然后发生的是 Spacer() 被压缩为空。解决这个问题的最简单方法是在 Spacer() 上放置一个 .frame(height: ???) 将导致 spacer 占用那个数量的 space 并推动你的 Form吃下。需要注意的是,它还会将您的圆圈推高并缩小。我不知道这对你来说是否是个问题,因为这是一个简单的最小的、可重现的例子,但如果需要,你可以在上面的视图上设置一个 .frame()

        VStack {
            Circle().foregroundColor(.yellow).overlay(VStack {
                Text("Example")
            }).foregroundColor(.primary)
            .frame(width: 300)
            
            Spacer()
                .frame(height: 100)
            
            Form {
                TextField("test", text: $a)
                TextField("test2", text: $b)
            }
        }

所有滚动视图(Form 建立在其上)和形状(Circle 是)在布局优先级上都是贪婪的。他们没有内部限制,所以如果有可用的 space whey gonna take it

Spacer 也是贪心的,但它的优先级低于其他贪心视图

这就是为什么在你的情况下 FormCircle 可以拆分 space 50% 到 50%

您需要限制他们的身高才能正常工作。

VStack {
    Circle().foregroundColor(.yellow).overlay(VStack {
        Text("Example")
    }).foregroundColor(.primary)
    .frame(height: UIScreen.main.bounds.width)
    
    Spacer()
    
    Form {
        TextField("test", text: $a)
        TextField("test2", text: $b)
    }.frame(height: 150)
}

解决这个问题的方法是使用 SwiftUI-Introspect.

,因为没有固定尺寸,所以在所有设备上看起来都不错

您可以通过从基础 UITableView.

获取 FormcontentHeight 来实现此目的

示例:

struct ContentView: View {
    @State private var a = ""
    @State private var b = ""

    @State private var contentHeight: CGFloat?

    var body: some View {
        VStack {
            Circle()
                .foregroundColor(.yellow)
                .overlay(
                    VStack {
                        Text("Example")
                    }
                )
                .foregroundColor(.primary)
                .aspectRatio(1, contentMode: .fit)

            Spacer()

            Form {
                TextField("test", text: $a)

                TextField("test2", text: $b)
            }
            .introspectTableView { tableView in
                contentHeight = tableView.contentSize.height
            }
            .frame(height: contentHeight)
        }
    }
}

结果: