SwiftUI VStack 和 List 中被其他视图压缩的视图

Views compressed by other views in SwiftUI VStack and List

在我的 SwiftUI 应用程序中,我正在尝试实现一个类似于此的 UI:

我为类别 1 和类别 2 添加了两行。结果如下所示:

NavigationView {
    VStack(alignment: .leading) {
        CategoryRow(...)
        CategoryRow(...)
        Spacer()
    }
    .navigationBarTitle(Text("Featured"))
}

现在,当添加第三个类别的视图时 - VStack 带有图像 - 会发生以下情况:

这发生了,在我用 VStack:

替换 Spacer() 之后
VStack(alignment: .leading) {
    Text("Rivers")
        .font(.headline)
    ForEach(self.categories["Rivers"]!.identified(by: \.self)) { landmark in
        landmark.image(forSize: 200)
    }
}

我的CategoryRow实现如下:

VStack(alignment: .leading) {
    Text(title)
        .font(.headline)
    ScrollView {
        HStack {
            ForEach(landmarks) { landmark in
                CategoryItem(landmark: landmark, isRounded: self.isRounded)
            }
        }
    }
}

问题

看来浏览量被压缩了。我找不到任何压缩阻力或内容拥抱优先级修改器来解决这个问题。
我还尝试在 CategoryRow.

上使用 .fixedSize().frame(width:height:)

如何防止压缩这些视图?


更新

我试过将整个外部堆栈视图嵌入到滚动视图中:

NavigationView {
    ScrollView { // also tried List
        VStack(alignment: .leading) {
            CategoryRow(...)
            CategoryRow(...)
            ForEach(...) { landmark in
                landmark.image(forSize: 200)
            }
        }
        .navigationBarTitle(Text("Featured"))
    }
}

...结果更糟:

我认为最顶层的视图(在 NavigationView 中)需要是一个列表,这样它才可以滚动:

NavigationView {
            List {
                ...

或者使用 ScrollView。

堆栈自动适合屏幕。如果你想让你的内容超过这个,你会在 UIKit

中使用 ScrollView 或 TableView 等

编辑:

实际上,稍微谷歌一下就得到了这个结果,这似乎正是你正在做的: https://developer.apple.com/tutorials/swiftui/composing-complex-interfaces

您在 VStack 中的所有视图似乎都不够 space,它压缩了其中的一些视图。您可以将其嵌入 ScrollView

NavigationView {
 ScrollView {
   VStack(alignment: .leading) {
      CategoryRow(...)
      CategoryRow(...)
      /// you images and so on
   }
  }
}

您可以通过使用

来阻止 VStack 中的视图被压缩
  .fixedSize(horizontal: false, vertical: true)

例如: 我有以下 VStack:

VStack(alignment: .leading){
        ForEach(group.items) {
            FeedCell(item: [=11=])
        }
    }

渲染压缩的 Text()

当我添加 .fixedSize(horizo​​ntal: false, vertical: true) 它不再压缩

VStack(alignment: .leading){
        ForEach(group.items) {
            FeedCell(item: [=12=])
                .fixedSize(horizontal: false, vertical: true)
        }
    }

您可以尝试向您的第一个 VStack 添加一个 layoutPriority() 运算符。这是文档对方法的描述:

In a group of sibling views, raising a view’s layout priority encourages that view to shrink later when the group is shrunk and stretch sooner when the group is stretched.

所以有点像Autolayout中的内容抗压缩优先级。但是这里的默认值是0,所以你只需要将它设置为1就可以得到想要的效果,像这样:

VStack(alignment: .leading) {
    CategoryRow(...)
    CategoryRow(...)
    Spacer()
}.layoutPriority(1)
VStack(alignment: .leading) {
    ...
}

希望有用!

struct ContentView1: View {
    var body: some View {
        NavigationView {
            ScrollView {
                VStack {
                    CategoryListView {
                        CategoryView()
                    }

                    CategoryListView {
                        SquareCategoryView()
                    }
                    
                    CategoryListView {
                        RectangleCategoryView()
                    }
                }
                .padding()
            }
            .navigationTitle("Featured")
        }
    }
}

struct CategoryListView<Content>: View where Content: View {
    private let viewSize: CGFloat = 150
    var content: () -> Content
    
    init(@ViewBuilder content: @escaping () -> Content) {
        self.content = content
    }
    
    var body: some View {
        VStack {
            HStack {
                Text("Category name")
                Spacer()
            }
            ScrollView(.horizontal, showsIndicators: false){
                HStack {
                    ForEach(0..<10) { _ in
                        content()
                    }
                }
            }
        }
    }
}

struct ContentView1_Previews: PreviewProvider {
    static var previews: some View {
        ContentView1()
    }
}

struct CategoryView: View {
    private let viewSize: CGFloat = 150
    var body: some View {
        Circle()
            .fill()
            .foregroundColor(.blue)
            .frame(width: viewSize, height: viewSize)
    }
}

struct RectangleCategoryView: View {
    private let viewSize: CGFloat = 350
    var body: some View {
        Rectangle()
            .fill()
            .foregroundColor(.blue)
            .frame(width: viewSize, height: viewSize * 9 / 16)
    }
}

struct SquareCategoryView: View {
    private let viewSize: CGFloat = 150
    var body: some View {
        Rectangle()
            .fill()
            .foregroundColor(.blue)
            .frame(width: viewSize, height: viewSize)
    }
}