0

I'm trying to align text in two different HStacks but having difficulties getting the second (shorter length) one to align with the first HStack. I've tried using .frame(minWidth:0, maxWidth: .infinity) and Spacer()'s but can't find a solution. Is this possible at all?

struct ContentView: View {
var body: some View {
    VStack(alignment: .leading) {
        HStack {
            Spacer()
            Text("Lorem ipsum dolor")
                .font(.system(size: 22, weight: .ultraLight, design: .rounded))
            Spacer()
        }.padding()
        .overlay(
            Rectangle()
                .stroke(Color(#colorLiteral(red: 0.6000000238, green: 0.6000000238, blue: 0.6000000238, alpha: 1)), style: StrokeStyle(lineWidth: 0.5, dash: [5.0])))
       
        
        HStack {
            Spacer()
            Text("Lorem ipsum")
                .font(.system(size: 22, weight: .ultraLight, design: .rounded))
            Spacer()
        }.padding()
        .overlay(
            Rectangle()
                .stroke(Color(#colorLiteral(red: 0.6000000238, green: 0.6000000238, blue: 0.6000000238, alpha: 1)), style: StrokeStyle(lineWidth: 0.5, dash: [5.0])))
    }
  }
}

What I currently have

I attempted to use a HorizontalAlignment guide, but they became off-centred:

struct ContentView: View {
var body: some View {
    VStack(alignment: .controlLeadingEdge) {
        HStack {
            Text("Lorem ipsum dolor")
                .font(.system(size: 22, weight: .ultraLight, design: .rounded))
                .alignmentGuide(.controlLeadingEdge, computeValue: { d in d[HorizontalAlignment.leading] })
        }.padding()
        .frame(minWidth: 0, maxWidth: 300)
        .overlay(
            Rectangle()
                .stroke(Color(#colorLiteral(red: 0.6000000238, green: 0.6000000238, blue: 0.6000000238, alpha: 1)), style: StrokeStyle(lineWidth: 0.5, dash: [5.0])))
        
        HStack {
            Text("Lorem ipsum")
                .font(.system(size: 22, weight: .ultraLight, design: .rounded))
                .alignmentGuide(.controlLeadingEdge, computeValue: { d in d[HorizontalAlignment.leading] })
        }.padding()
        .frame(minWidth: 0, maxWidth: 300)
        .overlay(
            Rectangle()
                .stroke(Color(#colorLiteral(red: 0.6000000238, green: 0.6000000238, blue: 0.6000000238, alpha: 1)), style: StrokeStyle(lineWidth: 0.5, dash: [5.0])))
        
    }
 }
}

extension HorizontalAlignment {
private enum ControlAlignment: AlignmentID {
    static func defaultValue(in context: ViewDimensions) -> CGFloat {
        return context[HorizontalAlignment.controlLeadingEdge]
    }
}
static let controlLeadingEdge = HorizontalAlignment(ControlAlignment.self)
}

HorizontalAlignment Attempt

2
  • How do you want it aligned? Do you want the longest one centered and the other aligned to the leading edge of the longest? Is the second one always shorter? Commented Nov 22, 2020 at 0:24
  • @vacawama I wanted to have the shortest one aligned to the leading edge of the longest. Yes that's correct, the second one will also be shorter. Thanks Commented Nov 22, 2020 at 0:35

1 Answer 1

2

Here is one way to do it:

Repeat the first text, give it .opacity(0) and put it in a ZStack with .leading alignment

struct ContentView: View {
    var body: some View {
        let firstText = Text("Loren ipsum dolor")
        let secondText = Text("Loren ipsum")
        
        VStack(alignment: .leading) {
            HStack {
                Spacer()
                firstText
                    .font(.system(size: 22, weight: .ultraLight, design: .rounded))
                Spacer()
            }.padding()
            .overlay(
                Rectangle()
                    .stroke(Color(#colorLiteral(red: 0.6000000238, green: 0.6000000238, blue: 0.6000000238, alpha: 1)), style: StrokeStyle(lineWidth: 0.5, dash: [5.0])))
            
            HStack {
                Spacer()
                ZStack(alignment: .leading) {
                    firstText.opacity(0)
                    secondText
                }
                .font(.system(size: 22, weight: .ultraLight, design: .rounded))
                Spacer()
            }.padding()
            .overlay(
                Rectangle()
                    .stroke(Color(#colorLiteral(red: 0.6000000238, green: 0.6000000238, blue: 0.6000000238, alpha: 1)), style: StrokeStyle(lineWidth: 0.5, dash: [5.0])))
        }
    }
}
Sign up to request clarification or add additional context in comments.

4 Comments

Thank you very much! I have a follow up question, if you wouldn't mind answering? When looking at ways to fix it, I looked at using Alignment guides but the HStacks became off-centred. Is this down to SwiftUI or would I have to play around with them a bit more?
I've updated my answer to show the HorizontalAlignment example if you wouldn't mind having a look?
The alignment guides do move the views around, which is why the outlines no longer align. I don't see an obvious way to get the aligned text without moving the outlines.
Oh ok, thank you for the explanation and original answer.

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.