2

Here is a visual of my Swift project so far.

enter image description here

I want to have a consistent padding around each description. As you can see, that is not being achieved, even though I applied a consistent padding constant. I think the problem has to do with each text block and their different spacings. I.E the second one has a space right after "hairs" but ends before the space, perhaps adding the space to the .leading padding somehow. Also note that the .leading padding for the images are shifted correspondingly.

Because the text in these blocks will eventually come from user input (not the random text I have here) it is critical that consistent padding is applied with any combination of text and spaces.

What is going wrong here?

Current code:

struct Header: View {
    var name: String
    var connection: String
    var image: String
    
    init(name: String, connection: String, image: String) {
        self.name = name
        self.connection = connection
        self.image = image
    }
    
    var body: some View {
        HStack() {
            Image(self.image)
                .resizable()
                .frame(width: 60, height: 60)
                .clipShape(Circle())
            VStack(alignment: .leading) {
                Text(self.name)
                    .font(.headline)
                    .fontWeight(.semibold)
                    .foregroundColor(Color.black)
                    .frame(alignment: .leading)
                Text(self.connection)
                    .font(.callout)
                    .fontWeight(.medium)
                    .foregroundColor(Color.gray)
                    .frame(alignment: .leading)
            
            }
        }
    }
}


struct Description: View {
    var description: String
    
    init(description: String) {
        self.description = description
    }
    
    var body: some View {
        Text(self.description)
            .multilineTextAlignment(.leading)
    }
}


struct Post: View {
    var data: PostData
    
    init(data: PostData) {
        self.data = data
    }
    
    var body: some View {
        HStack(alignment: .top) {
            Spacer()
                .frame(width: 110)
            VStack(alignment: .leading, spacing: 0.0) {
                Header(name: self.data.name, connection: self.data.connection, image: self.data.image)
                    .padding(.top, 10)
                    .padding(.bottom, 6)
                    .padding(.leading, 6)
                Description(description: self.data.description)
                    .padding(.bottom, 6)
                    .padding(.leading, 7)
                    .padding(.trailing, 5)
                    
            }
            .frame(maxWidth: .infinity)
            .border(Color.black)
        }
    }
}



struct PostView: View {
    var body: some View {
        VStack(spacing: -1.0) {
            Spacer()
            Post(data: one)
            Post(data: two)
            Post(data: three)
        }
    }
}
      
2
  • Not sure if this will fix the issue, but you could try adding a fixed size to the stack that contains your body text. Add to the closing curly bracket on whichever stack contains your body text something like the following : .fixedSize(horizontal: false, vertical: true) Commented Jul 25, 2021 at 21:03
  • 1
    That isn’t really padding, it is remainder space. The text is centered and fitted as apple sees fit. You can push it left or set the alignment so it starts at the same spot Commented Jul 25, 2021 at 21:49

1 Answer 1

5

Matt (in the comments) is completely correct. I just got confused by the nested VStacks. This is much more easily fixed and makes perfect sense. The alignment is supposed to be at the top level:

struct PostView: View {
    var body: some View {
        VStack(alignment: .leading, spacing: -1.0) { // <=== here
            Spacer()
            Post(data: one)
            Post(data: two)
            Post(data: three)
        }
    }
}

The problem is that your alignment is applied at the Post level, but each Post is then centered based on its own width. The width of the misaligned post is a little smaller than the others.


OLD ANSWER:

Fixing it is straightforward. Explaining it is still a mystery to me. (Fixed: See below)

The Text for this post requires a little less space than the others, and that's leading to it being centered. What isn't clear to me is why the alignment: .leading doesn't align it.

The fix, as with most "push to an edge" issues, is a Spacer:

VStack(alignment: .leading, spacing: 0.0) {
    Header(name: self.data.name, connection: self.data.connection, image: self.data.image)
        .padding(.top, 10)
        .padding(.bottom, 6)
        .padding(.leading, 6)
    HStack {
        Description(description: self.data.description)
            .padding(.bottom, 6)
            .padding(.leading, 7)
            .padding(.trailing, 5)
        Spacer() // <== Left-justify
    }

This will push the text to the left the way you want. But I don't have a good answer about why it's needed.

Another approach that might be a little easier to reason about is to replace the padding with explicit Spacers:

HStack {
    Spacer().frame(width: 7)
    Description(description: self.data.description)
    Spacer(minLength: 5)
}
.padding(.bottom, 6)
Sign up to request clarification or add additional context in comments.

2 Comments

Here’s the explanation: Even though the Description’s VStack alignment is .leading, the VStack itself isn’t taking up the full width because of the tight frame around the wrapped text. This, in turn, causes the Post to be centered in the top-level VStack. That’s why the Header and Description line up.
@MattPennig Thank you. This is a much better explanation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.