VStack inside ForEach loop not respecting alignment parameter in WatchOS

Viewed 1671

I have a VStack with alignment .leading inside of a ForEach loop inside a ScrollView and the alignment parameter is not being respected. If I have a single VStack outside of the ForEach loop the alignment parameter is being used and the view is displayed correctly.

    ScrollView{
        // THIS DISPLAYS CORRECTLY
        VStack(alignment: .leading){
            Text("namename")
                .font(.headline)
                .lineLimit(1)
            Text("namename  name")
                .font(.subheadline)
                .lineLimit(1)
        }
        .padding()
        .frame(minWidth: 0, maxWidth: .infinity)
        .background(Color.gray.opacity(0.20))
        .cornerRadius(5)
        .padding(.bottom)

        ForEach(self.list_of_names, id: \.self) { item in
            // THIS DOES NOT DISPLAY CORRECTLY
            VStack(alignment: .leading){
                Text(item)
                    .font(.headline)
                    .lineLimit(1)
                Text(item + " name")
                    .font(.subheadline)
                    .lineLimit(1)
            }
            .frame(minWidth: 0, maxWidth: .infinity)
            .background(Color.gray.opacity(0.20))
            .cornerRadius(5)
            .padding(.bottom)
        }

    }
    .padding()

enter image description here

The first row has the correct alignment and it's outside the ForEach loop, meanwhile the other rows are inside the loop. The blue lines represent me highlighting each VStack inside the ForEach loop

2 Answers

The VStacks created in the ForEach loop do seem to be conforming to the alignment parameter. Aligning the text to the leading edge only applies to the shorter items in the VStack.

In the top VStack, "namename" at the top is only that far to the left because "namename name" below is that much wider from the center of the ScrollView. So the top VStack is not the proper way to fully achieve the alignment that you want to the ScrollView.

What you're looking for:

Leave the alignment parameter for VStack.

Add the alignment parameter to the frame of the VStack.

.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)

I'm a bit late, but another solution I usually use is wrapping the values in an HStack and adding a Spacer. Something like this will achieve the desired effect:

var body: some View {
    ScrollView {
        ForEach(self.list_of_names, id: \.self) { item in
            HStack {
                VStack(alignment: .leading) {
                    Text(item)
                        .font(.headline)
                        .lineLimit(1)
                    Text(item + " name")
                        .font(.subheadline)
                        .lineLimit(1)
                }
                Spacer()
            }
            .padding()
            .frame(minWidth: 0, maxWidth: .infinity)
            .background(Color.gray.opacity(0.20))
            .cornerRadius(5)
            .padding(.bottom)
        }

    }
    .padding()
}
Related