如何在 SwiftUI 中创建“类似约束”的布局

问题描述 投票:0回答:1

来自 UIKit,我发现在 SwiftUI 中很难达到预期的结果。我假设我会陷入约束驱动布局中,以了解 SwiftUI 方法。

假设以下布局:

  • 在具有“常规”屏幕的设备上,水平空间应按 1:1 分为顶部和底部部分。

  • 顶部容器包含固定高度的三个视图,应位于容器的顶部、中心和底部。

  • 三个视图有一些最小间距,例如20 像素。如果有足够的空间,间距可以更大,但绝不能低于 20 像素。

  • 在较小的设备上,顶部容器可以缩小到一定程度。但永远不会太小,以至于会违反子视图的固定宽度及其间距。在这种情况下,顶部和底部容器之间的比例将不再是 1:1,而是例如2:3.

  • 在 iPad 等较大设备上,顶部容器只会增长到某个最大值。高度。在这种情况下,顶部和底部容器之间的比例也不再是 1:1。

  • 底部容器视图仅包含一个视图,该视图应始终填充可用空间。

enter image description here

使用 UIKit 中的约束来解决这个问题是没有问题的。我知道“常规”、“较小”和“较大”设备并不是实际的尺寸类别。这只是为了说明。

但是在 SwiftUI 中如何解决这个问题?

基本布局当然是直接的:

VStack(spacing: 0) {
    VStack {
        TopView()
        Spacer()
        CenterView()
        Spacer()
        BottomView()
    }
    .frame(maxWidth: .infinity, maxHeight: .infinity)
    .background(.red)
    
    VStack {
        FillView()
    }
    .frame(maxWidth: .infinity, maxHeight: .infinity)
    .background(.green)
}

但是如何实现top-container的min-和maxHeight呢?是否可以不使用

GeometryReader
而仅使用相对值来做到这一点?

当底部容器因其内容而变大时,如何避免将顶部容器收缩到给定的最小高度以下?

ios swiftui layout
1个回答
0
投票

我认为您可以通过一些小更改来非常接近您的要求:

  • 带有
    VStack
    Spacer
    将在其包含的视图之间添加一些(默认)间距,因此这包括
    Spacer
    周围的一些额外间距。为了强制执行 20 点最小间距,我建议在
    spacing: 20
    上使用
    VStack
    ,然后删除
    Spacer
    并在
    maxHeight: .infinity
    上设置
    CenterView
VStack(spacing: 20) {
    TopView()
    CenterView()
        .frame(maxHeight: .infinity)
    BottomView()
}
  • 对于较大屏幕的情况,在上部
    maxHeight
    上设置有限的
    VStack
    ,而不是
    .infinity
VStack(spacing: 20) {
    // ...
}
.padding()
.frame(maxWidth: .infinity, maxHeight: 400)
.background(.red)
  • 较小屏幕的要求是唯一不太容易完全满足的要求。您可能会有一个阈值高度,低于该高度,布局会从 1:1 的比例切换到 2:3 的比例。您可以通过在
    FillView
    上设置最小高度(根据阈值高度计算)来实现类似的效果:
FillView()
    .frame(maxWidth: .infinity, minHeight: 200, maxHeight: .infinity)
    .background(.green)

请注意,所有 iPhone 的横向高度甚至比最小的 iPhone 纵向高度还要小。

把它们放在一起:

VStack(spacing: 0) {
    VStack(spacing: 20) {
        TopView()
        CenterView()
            .frame(maxHeight: .infinity)
        BottomView()
    }
    .padding()
    .frame(maxWidth: .infinity, maxHeight: 400)
    .background(.red)

    FillView()
        .frame(maxWidth: .infinity, minHeight: 200, maxHeight: .infinity)
        .background(.green)
}

使用比率分配空间的另一种方法是使用自定义

Layout
。按权重水平分布视图的示例实现可以在 SwiftUI How to Set Specific Width Ratios for Child Elements in an HStack(这是我的答案)的答案中找到。

© www.soinside.com 2019 - 2024. All rights reserved.