根据SwiftUI中的内容制作VStack高度

根据SwiftUI中的内容制作VStack高度,swiftui,height,geometryreader,Swiftui,Height,Geometryreader,我想制作一张“卡片”,但高度取决于物品列表,我不知道如何根据我的尺寸列表设置不同的值。。。例如: ContentView结构 struct ContentView: View { @State private var orderList : [Order] = [ Order(id: 0, productList: [Product(id: 0, name: "itemA", quantity: "24"

我想制作一张“卡片”,但高度取决于物品列表,我不知道如何根据我的尺寸列表设置不同的值。。。例如:

ContentView结构

struct ContentView: View {
    
    @State private var orderList : [Order] = [
        
        Order(id: 0, productList: [Product(id: 0, name: "itemA", quantity: "24", isEvaluated: true), Product(id: 0, name: "itemB", quantity: "2", isEvaluated: false)]),
        
        Order(id: 1, productList: [Product(id: 0, name: "itemC", quantity: "4", isEvaluated: true), Product(id: 0, name: "itemD", quantity: "12", isEvaluated: false),Product(id: 0, name: "itemE", quantity: "6", isEvaluated: false), Product(id: 0, name: "itemF", quantity: "5", isEvaluated: false)]),
                                   
        Order(id: 2, productList: [Product(id: 0, name: "itemG", quantity: "24", isEvaluated: true)]),
        
        
        Order(id: 3, productList: [Product(id: 0, name: "itemH", quantity: "5", isEvaluated: true), Product(id: 0, name: "itemI", quantity: "2", isEvaluated: false),Product(id: 0, name: "itemJ", quantity: "16", isEvaluated: false), Product(id: 0, name: "itemK", quantity: "4", isEvaluated: false), Product(id: 0, name: "itemL", quantity: "2", isEvaluated: false)]),
        
        Order(id: 4, productList: [Product(id: 0, name: "itemM", quantity: "8", isEvaluated: true)])
    ]
    
    
    var body: some View {
        VStack{
            ForEach(orderList, id: \.self){order in
                ScrollView(showsIndicators: false){
                    VStack(alignment: .leading){
                        Group{
                            HStack{
                                Text("#Order " + "\(order.id)").multilineTextAlignment(.center)
                                Spacer()
                                Text("In Progress").multilineTextAlignment(.center)
                            }.padding([.bottom],5)
                        }
                        
                        Group{
                            VStack{
                                ForEach(order.productList.indices) { currentIndex in
                                ItemRow(getProduct(productList: order.productList, index: currentIndex))
                                        .padding(.bottom, 5)
                                }
                            }
                        }.padding([.bottom], 10)
                        
                        HStack{
                            Text("Products")
                            Spacer()
                            Text("$00.00")
                        }
                        
                        HStack{
                            Text("Shipping Expenses")
                            Spacer()
                            Text("$00.00")
                        }
                        
                        HStack{
                            Text("Total")
                            Spacer()
                            Text("$0.00")
                        }
                        Spacer()
                    }
                    .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .topLeading)
                    .padding(10)
                    
                }
                .background(
                    RoundedRectangle(cornerRadius: 2)
                        .fill(Color.white)
                        .shadow(color: .gray, radius: 2, x: 0, y: 2)
                )
                .padding(.bottom, 10)
            }
         }
         .padding(16)
    }
    
    func getProduct(productList: [Product], index: Int)-> Product{
        return productList[index]
    }
}
struct ItemRow: View {
    
    let currentProduct: Product
    
    init(_ currentProduct: Product) {
        self.currentProduct = currentProduct
    }
        
    var body: some View {
        HStack{
            HStack{
                Text("• \(currentProduct.name)")
                Spacer()
            }
            HStack{
                Text("quantity \(currentProduct.quantity)")
                Spacer()
            }
            
            if !currentProduct.isEvaluated{
                HStack{
                    Spacer()
                    Button(action:{
                        // do sth
                    }){
                        Text("rate now!")
                    }
                }
            }
        }
    }
}

项目行结构

struct ContentView: View {
    
    @State private var orderList : [Order] = [
        
        Order(id: 0, productList: [Product(id: 0, name: "itemA", quantity: "24", isEvaluated: true), Product(id: 0, name: "itemB", quantity: "2", isEvaluated: false)]),
        
        Order(id: 1, productList: [Product(id: 0, name: "itemC", quantity: "4", isEvaluated: true), Product(id: 0, name: "itemD", quantity: "12", isEvaluated: false),Product(id: 0, name: "itemE", quantity: "6", isEvaluated: false), Product(id: 0, name: "itemF", quantity: "5", isEvaluated: false)]),
                                   
        Order(id: 2, productList: [Product(id: 0, name: "itemG", quantity: "24", isEvaluated: true)]),
        
        
        Order(id: 3, productList: [Product(id: 0, name: "itemH", quantity: "5", isEvaluated: true), Product(id: 0, name: "itemI", quantity: "2", isEvaluated: false),Product(id: 0, name: "itemJ", quantity: "16", isEvaluated: false), Product(id: 0, name: "itemK", quantity: "4", isEvaluated: false), Product(id: 0, name: "itemL", quantity: "2", isEvaluated: false)]),
        
        Order(id: 4, productList: [Product(id: 0, name: "itemM", quantity: "8", isEvaluated: true)])
    ]
    
    
    var body: some View {
        VStack{
            ForEach(orderList, id: \.self){order in
                ScrollView(showsIndicators: false){
                    VStack(alignment: .leading){
                        Group{
                            HStack{
                                Text("#Order " + "\(order.id)").multilineTextAlignment(.center)
                                Spacer()
                                Text("In Progress").multilineTextAlignment(.center)
                            }.padding([.bottom],5)
                        }
                        
                        Group{
                            VStack{
                                ForEach(order.productList.indices) { currentIndex in
                                ItemRow(getProduct(productList: order.productList, index: currentIndex))
                                        .padding(.bottom, 5)
                                }
                            }
                        }.padding([.bottom], 10)
                        
                        HStack{
                            Text("Products")
                            Spacer()
                            Text("$00.00")
                        }
                        
                        HStack{
                            Text("Shipping Expenses")
                            Spacer()
                            Text("$00.00")
                        }
                        
                        HStack{
                            Text("Total")
                            Spacer()
                            Text("$0.00")
                        }
                        Spacer()
                    }
                    .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .topLeading)
                    .padding(10)
                    
                }
                .background(
                    RoundedRectangle(cornerRadius: 2)
                        .fill(Color.white)
                        .shadow(color: .gray, radius: 2, x: 0, y: 2)
                )
                .padding(.bottom, 10)
            }
         }
         .padding(16)
    }
    
    func getProduct(productList: [Product], index: Int)-> Product{
        return productList[index]
    }
}
struct ItemRow: View {
    
    let currentProduct: Product
    
    init(_ currentProduct: Product) {
        self.currentProduct = currentProduct
    }
        
    var body: some View {
        HStack{
            HStack{
                Text("• \(currentProduct.name)")
                Spacer()
            }
            HStack{
                Text("quantity \(currentProduct.quantity)")
                Spacer()
            }
            
            if !currentProduct.isEvaluated{
                HStack{
                    Spacer()
                    Button(action:{
                        // do sth
                    }){
                        Text("rate now!")
                    }
                }
            }
        }
    }
}

注意:在itemsList中,您必须创建一个名为
Order
struct
,如下所示:(不要介意硬代码值,我这样做是为了使示例更简单)

PS2。在productList中,必须创建名为
Product
struct
,如下所示:

struct Product: Hashable {
    var id: Int
    var name: String
    var quantity : String
    var isEvaluated : Bool
}
var body: some View {
    ScrollView {
        ForEach(orderList, id: \.self){order in
            VStack(alignment: .leading){
                Group{
                    HStack{
                        Text("#Order " + "\(order.id)").multilineTextAlignment(.center)
                        Spacer()
                        Text("In Progress").multilineTextAlignment(.center)
                    }.padding([.bottom],5)
                }
                
                Group{
                    VStack{
                        ForEach(order.productList.indices) { currentIndex in
                        ItemRow(getProduct(productList: order.productList, index: currentIndex))
                                .padding(.bottom, 5)
                        }
                    }
                }.padding([.bottom], 10)
                
                HStack{
                    Text("Products")
                    Spacer()
                    Text("$00.00")
                }
                
                HStack{
                    Text("Shipping Expenses")
                    Spacer()
                    Text("$00.00")
                }
                
                HStack{
                    Text("Total")
                    Spacer()
                    Text("$0.00")
                }
                Spacer()
            
            }.background(
                RoundedRectangle(cornerRadius: 2)
                    .fill(Color.white)
                    .shadow(color: .gray, radius: 2, x: 0, y: 2)
            )
            .padding(.bottom, 10)
        }
     }
     .padding(16)
}

如果我理解正确,您希望卡片(红框)占用尽可能多的空间来显示内容,而无需在卡片上滚动

简短的回答。你不需要

SwiftUI为您做这件事。您在
ContentView
中的代码中只有一个小错误。将
ScrollView
移动到您拥有
VStack
的位置,然后移除
VStack
。您的
ContentView
body
现在应该如下所示:

struct Product: Hashable {
    var id: Int
    var name: String
    var quantity : String
    var isEvaluated : Bool
}
var body: some View {
    ScrollView {
        ForEach(orderList, id: \.self){order in
            VStack(alignment: .leading){
                Group{
                    HStack{
                        Text("#Order " + "\(order.id)").multilineTextAlignment(.center)
                        Spacer()
                        Text("In Progress").multilineTextAlignment(.center)
                    }.padding([.bottom],5)
                }
                
                Group{
                    VStack{
                        ForEach(order.productList.indices) { currentIndex in
                        ItemRow(getProduct(productList: order.productList, index: currentIndex))
                                .padding(.bottom, 5)
                        }
                    }
                }.padding([.bottom], 10)
                
                HStack{
                    Text("Products")
                    Spacer()
                    Text("$00.00")
                }
                
                HStack{
                    Text("Shipping Expenses")
                    Spacer()
                    Text("$00.00")
                }
                
                HStack{
                    Text("Total")
                    Spacer()
                    Text("$0.00")
                }
                Spacer()
            
            }.background(
                RoundedRectangle(cornerRadius: 2)
                    .fill(Color.white)
                    .shadow(color: .gray, radius: 2, x: 0, y: 2)
            )
            .padding(.bottom, 10)
        }
     }
     .padding(16)
}
这将为您提供以下结果:


非常感谢您!