0
votes

It could be a simple case, but I couldn't find a solution.

Here is my code, using the GeometryReader to set the relative layout of SwiftUI view size like Image. The issue in on the last VStack, I want to background of Text to go to the right end of VStack. Thus, I set it as Text("Haibo: asdasd").frame(maxWidth: .infinity) but after that I found the text became to horizontal centered and not followed the VStack alignment: .leading.

import SwiftUI

struct ContentView: View {
    var body: some View {

        GeometryReader { geo in
            HStack(alignment: .top, spacing: 12) {
                Image("Alan shore").resizable().frame(width: geo.size.width / 6, height: geo.size.width / 6).cornerRadius(4)

                VStack(alignment: .leading, spacing: 10) {

                   // name
                   Text("Haibo")
                   // content
                   Text("Think ThinkThink ThinkThink ThinkThink ThinkThink ThinkThink ThinkThink ThinkThink Think")
                   // 九宫格
                   VStack(spacing: 6) {

                       HStack(spacing: 6) {
                           Image("Little girl").resizable().frame(width: geo.size.width / 4.7, height: geo.size.width / 4.7)
                           Image("Little girl").resizable().frame(width: geo.size.width / 4.7, height: geo.size.width / 4.7)
                           Image("Little girl").resizable().frame(width: geo.size.width / 4.7, height: geo.size.width / 4.7)
                       }
                       HStack(spacing: 6) {
                           Image("Little girl").resizable().frame(width: geo.size.width / 4.7, height: geo.size.width / 4.7)
                           Image("Little girl").resizable().frame(width: geo.size.width / 4.7, height: geo.size.width / 4.7)
                           Image("Little girl").resizable().frame(width: geo.size.width / 4.7, height: geo.size.width / 4.7)
                       }
                       HStack(spacing: 6) {
                           Image("Little girl").resizable().frame(width: geo.size.width / 4.7, height: geo.size.width / 4.7)
                           Image("Little girl").resizable().frame(width: geo.size.width / 4.7, height: geo.size.width / 4.7)
                           Image("Little girl").resizable().frame(width: geo.size.width / 4.7, height: geo.size.width / 4.7)
                       }
                   }

                   // Time, Action
                   HStack {
                       Text("5 hour ago")
                       Spacer()
                       Image("moment-action")
                   }

                   // Comment
                   VStack(alignment: .leading) {
                       Text("Haibo: asdasd").frame(maxWidth: .infinity)
                       Text("Jobs: WDC WDC WDC WDCWWWWW")
                   } //.padding(.init(top: 6, leading: 6, bottom: 6, trailing: 12))
                       .background(Color.yellow)
                   .cornerRadius(3)
                }
            } .padding(.init(top: 12, leading: 12, bottom: 12, trailing: 30))
        }
    }
}


struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

Well, please see the screenshot for better understanding, the Text("Haibo: asdasd") is centered in the yellow area. How could let it to be keep leading alignment?

enter image description here

2

2 Answers

1
votes

This is a fairly confusing aspect of SwiftUI. The VStack alignment specifies how its elements align within the VStack frame, while the Text.frame alignment specifies how the text will align within the Text.frame.

I've found it helpful to add some borders as I'm debugging:

VStack(alignment: .leading) {
    Text("Haibo: asdasd")
        .frame(maxWidth: .infinity)
        .border(Color.red , width: 2.0)
    Text("Jobs: WDC WDC WDC WDCWWWWW")
        .border(Color.green , width: 2.0)
}

original way with borders

Now you can see that the Text with maxWidth: .infinity has a frame that spans the entire width of the VStack frame. The text frame is aligned leading, but the text within defaults to a center alignment.

It's worth mentioning here that the "jobs..." text is also center aligned to its text frame, but it's not obvious because the frame is sized to the text only, then the text frame itself is leading aligned within the VStack frame.

Now try this:

VStack(alignment: .leading) {
    Text("Haibo: asdasd")
        .frame(maxWidth: .infinity, alignment: .leading)
        .border(Color.red , width: 2.0)
    Text("Jobs: WDC WDC WDC WDCWWWWW")
        .border(Color.green , width: 2.0)
}

new way with borders

The text frame is still the full-width of the VStack frame, but the text is now aligned leading within the text frame.

Here's the snippet without the borders:

VStack(alignment: .leading) {
    Text("Haibo: asdasd")
        .frame(maxWidth: .infinity, alignment: .leading)
    Text("Jobs: WDC WDC WDC WDCWWWWW")
}

new way without borders

Here's an article I found helpful for sorting out how alignment works:

Alignment Guides in SwiftUI

0
votes

You should add .leading alignment to its frame, like

 VStack(alignment: .leading) {
           Text("Haibo: asdasd").frame(maxWidth: .infinity, alignment: .leading)
           Text("Jobs: WDC WDC WDC WDCWWWWW")
       }