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

Posted

技术标签:

【中文标题】SwiftUI VStack 和 List 中其他视图压缩的视图【英文标题】:Views compressed by other views in SwiftUI VStack and List 【发布时间】:2019-06-08 14:59:23 【问题描述】:

在我的 SwiftUI 应用程序中,我正在尝试实现类似这样的 UI:

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

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

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

这发生在我将Spacer()替换为VStack之后:

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

...结果更糟:

【问题讨论】:

你试过.scaledToFit()吗? 【参考方案1】:

你可能会阻止 VStack 中的视图被压缩使用

  .fixedSize(horizontal: false, vertical: true)

例如: 我有以下 VStack:

VStack(alignment: .leading)
        ForEach(group.items) 
            FeedCell(item: $0)
        
    

哪个渲染压缩的Text()

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

VStack(alignment: .leading)
        ForEach(group.items) 
            FeedCell(item: $0)
                .fixedSize(horizontal: false, vertical: true)
        
    

【讨论】:

谢谢。我有多行 Text()Image().resizable() 争取垂直空间,这样我就能够强制文本优先并抵抗压缩。【参考方案2】:

您可以尝试将layoutPriority() 运算符添加到您的第一个VStack。这是文档中关于该方法的内容:

在一组同级视图中,提高视图的布局优先级会鼓励该视图在组收缩时稍后收缩,并在组拉伸时更快地拉伸。

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

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

希望它有效!

【讨论】:

【参考方案3】:

似乎没有足够的空间容纳您在 VStack 中的所有视图,它会压缩其中的一些视图。您可以将其嵌入到ScrollView

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

【讨论】:

好吧,我就是这么做的,但同样的事情发生了:视图被压缩了,都使用了 ScrollView 和 List。【参考方案4】:
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)
    

【讨论】:

【参考方案5】:

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

NavigationView 
            List 
                ...

或者使用 ScrollView。

堆栈自动适应屏幕。如果您希望您的内容超出此范围,您将使用 ScrollView 或 TableView 等 i UIKit

编辑:

实际上,谷歌搜索带来了这个结果,这似乎正是您正在制作的: https://developer.apple.com/tutorials/swiftui/composing-complex-interfaces

【讨论】:

好吧,我确实做到了,但同样的事情发生了:视图被压缩,都使用 ScrollView 和 List。是的,我有那个教程的屏幕截图,但即使他们在那里显示,他们并没有完全实现那个 UI,而是 3 个类别行。由于每一个都不是很高,它们不会到达视图的底部,因此,首先不要被压缩。 查看我编辑的问题。我还尝试完全删除最顶层的堆栈视图,以便 CategoryRows 直接在 List/ScrollView 内 - 不走运。

以上是关于SwiftUI VStack 和 List 中其他视图压缩的视图的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Swiftui 中与其他组件一起在 ScrollView 或 VStack 中完全显示 Picker?

在列表行中制作等宽的 SwiftUI 视图

SwiftUI NavigationView 背景颜色

SwiftUI 点击手势阻止列表中的项目删除操作

SwiftUI,删除VStack中视图之间的空间?

SwiftUI:VStack中的VStack,标签被截断