SwiftUI:如何使视图适合特定大小

SwiftUI: how to make a view fit into a certain size

所以基本上我的应用程序中有这个视图。

我希望名为 LaMarcus Aldridge 的盒子与其他盒子大小相同基本上我想通过减少图片和文本行之间的 space 数量来减小盒子的大小,以便所有盒子尺寸相同。我最初考虑通过计算所需的 space 来从数学上解决这个问题,但我很确定有更好的方法来做到这一点,我只是没有想到。谢谢,真的很感激。

这是声明这些框的代码。

var body: some View {
        VStack(spacing: 15) { //first
            Image(uiImage: question.players[0].picture)
                .resizable()
                .aspectRatio(contentMode: .fit)
                .frame(height: 140)
//                .padding(.init(top: 0, leading: 0, bottom: 0, trailing: 0))
            
            Text(question.players[0].name)
                .font(.title2)
                .fontWeight(.heavy)
                .foregroundColor(.black)
                .multilineTextAlignment(.center)
                .lineLimit(2)
            
            Text(question.players[0].team)
                .foregroundColor(.black)
                .multilineTextAlignment(.center)
        }
        .padding()
        .frame(maxWidth: .infinity)
        .onTapGesture(perform: {
            selectedAnswer = question.players[0]
        })
        
        .background(
            RoundedRectangle(cornerRadius: 15)
                .stroke(color(option: question.players[0]), lineWidth: 5)
        )
        .cornerRadius(15)
        
        VStack(spacing: 15) { //second
            Image(uiImage: question.players[1].picture)
                .resizable()
                .aspectRatio(contentMode: .fit)
                .frame(height: 140)
            Text(question.players[1].name)
                .font(.title2)
                .fontWeight(.heavy)
                .foregroundColor(.black)
                .multilineTextAlignment(.center)
                .lineLimit(2)
            
            Text(question.players[1].team)
                .foregroundColor(.black)
                .multilineTextAlignment(.center)
        }
        
        .padding()
        .frame(maxWidth: .infinity)
        .onTapGesture(perform: {
            selectedAnswer = question.players[1]
        })
        .background(
            RoundedRectangle(cornerRadius: 15)
                .stroke(color(option: question.players[1]), lineWidth: 5)
        )
        .cornerRadius(15)
        
        VStack(spacing: 15) { //third
            Image(uiImage: question.players[2].picture)
                .resizable()
                .aspectRatio(contentMode: .fit)
                .frame(height: 140)
            Text(question.players[2].name)
                .font(.title2)
                .fontWeight(.heavy)
                .foregroundColor(.black)
                .multilineTextAlignment(.center)
                .lineLimit(2)
            
            Text(question.players[2].team)
                .foregroundColor(.black)
                .multilineTextAlignment(.center)
        }
        
        .padding()
        .frame(maxWidth: .infinity)
        .onTapGesture(perform: {
            selectedAnswer = question.players[2]
        })
        .background(
            RoundedRectangle(cornerRadius: 15)
                .stroke(color(option: question.players[2]), lineWidth: 5)
        )
        .cornerRadius(15)
        
        VStack(spacing: 15) { //fourth
            Image(uiImage: question.players[3].picture)
                .resizable()
                .aspectRatio(contentMode: .fit)
                .frame(height: 140)
            Text(question.players[3].name)
                .font(.title2)
                .fontWeight(.heavy)
                .foregroundColor(.black)
                .multilineTextAlignment(.center)
                .lineLimit(2)
            
            Text(question.players[3].team)
                .foregroundColor(.black)
                .multilineTextAlignment(.center)
        }
        
        .padding()
        .frame(maxWidth: .infinity)
        .onTapGesture(perform: {
            selectedAnswer = question.players[3]
        })
        .background(
            RoundedRectangle(cornerRadius: 15)
                .stroke(color(option: question.players[3]), lineWidth: 5)
        )
        .cornerRadius(15)
    }

尝试在VStack中使用conditional。 我创建了一个自定义卡片视图,您可以在您的内容视图中使用它,使用 LazyVGrid + ForEach 或简单地使用 HStack 和 VStack。

struct CardView: View{
var playerName: String
var playerTeam: String
var playerPortrait: UIImage
var body: some 
View{
 
//Control amount of spacing depend on amount of character in player's name
VStack(spacing: playerName.count  > 13 ? -12 : 0) { //first
    Image(uiImage: playerPortrait)
                .resizable()
                .aspectRatio(contentMode: .fit)
                .frame(height:160)
                .padding(10)
            
            Text(playerName)
                .foregroundColor(.black)
                .multilineTextAlignment(.center)
                .lineLimit(2)
                .padding(5)
            
            Text(playerTeam)
                .foregroundColor(.black)
                .multilineTextAlignment(.center)
                .padding(5)
}.background(RoundedRectangle(cornerRadius: 15).stroke()).padding(5)
}
}