2

In the sample below, if I have a VStack followed for a HStack, how can I make the width of the HStack follow the same as a grid ?

struct VStackAlignmentView: View {
    let data = ["a", "b", "cdefghl alalala", "i", "j"]
    var body: some View {
        VStack(spacing: 0) {
            ForEach (data, id:\.self) { item in
                HStack(alignment: .top) {
                    Text("Column 1")
                    VStack(alignment: .trailing) {
                        Text("Column \(item)")
                        Text("Value 2")
                    }
                    .frame(minWidth: 120)
                    Text("Column 3")
                    Spacer()
                }
            }
        }
    }
}

This is the result I got: Result of the code above The text on the 3rd row is aligned to the right, but the other rows it adds a space to that

I have tried a hack to for the VStack(alignment: .trailing) by adding an empty Text with the frame width and it works, but I don't think that is an elegant way.

I also tried to use alignmentGuide but it push the views to other way.

Anyone with the same problem?

1
  • 1
    Not sure I got what were you trying to achieve. Could you sketch somehow?
    – Asperi
    Commented Nov 23, 2020 at 16:16

1 Answer 1

7

Using you're code, I believe this is what you're looking for:

struct VStackAlignmentView: View {
    let data = ["a", "b", "cdefghl alalala", "i", "j"]
    
    var body: some View {
        VStack(alignment: .center, spacing: 20) {
            ForEach (data, id:\.self) { item in
                HStack(alignment: .top, spacing: 20) {
                    Text("Column 1")
                    VStack(alignment: .center) {
                        Text("Column \(item)")
                        Text("Value 2")
                    }
                    .frame(minWidth: 120)
                    Text("Column 3")
                }
                .frame(maxWidth: .infinity)

            }
        }
        .multilineTextAlignment(.center)
        .frame(maxWidth: .infinity)
    }
}

But if you're just creating a grid layout, it will be much easer to use a LazyGrid:

struct VStackAlignmentView2: View {
    let data = ["a", "b", "cdefghl alalala", "i", "j"]
    
    var body: some View {
        LazyVGrid(
            columns: [
                GridItem(.flexible()), GridItem(.flexible()), GridItem(.flexible())
            ],
            alignment: .center,
            spacing: 10,
            pinnedViews: [],
            content: {
                ForEach (data, id:\.self) { item in
                    Text(item)
                }
            })
    }
}

Not the answer you're looking for? Browse other questions tagged or ask your own question.