Search code examples
iostextswiftuialignmenthstack

When there are different sized Text in a HStack, top alignment doesn’t apply to larger sized text


I have a HStack with multiple elements, particularly two Texts with different font sizes. I want both text to be aligned to the top of the view.

HStack(alignment: .top) {
    Image(systemName: "cloud.drizzle.fill")
    Text("14°")
        .font(.largeTitle)
    Text("86%")
        .font(.callout)
    Spacer()
}

However, the first (larger) Text is outputted below the other two:

enter image description here


Solution

  • Actually it's aligned correctly , add backgrounds to each Text and you will find that the frame of the Text is aligned correctly

    but to solve the case that you are looking for , I did a hack for you , by doing some calculs

    The result:

    enter image description here

    1) Alignement of the two Text

    • Put both of them in one HStack , with alignment: .firstTextBaseline
    • Then play on the second text , by adding a baselineOffset with (bigFont.capHeight - smallFont.capHeight)

    You can learn more about fonts , but the main information that you need is this :

    enter image description here

    So your code will be :

     HStack(alignment: .firstTextBaseline) {
                    Text("14°")
                        .font(Font(bigFont))
                        .background(Color.blue)
                    
                    Text("86%")
                        .font(Font(smallFont))
                        .baselineOffset((bigFont.capHeight - smallFont.capHeight))
                        .background(Color.yellow)
                    Spacer()
                }
    

    2) Align the Image with the text :

    • by adding a padding which will be equal to bigFont.lineHeight-bigFont.ascender (go back to the picture on top , to see how I calculated it )

    And the final code :

    struct ContentView: View {
        @State var pickerSelection = ""
        
        let bigFont = UIFont.systemFont(ofSize: 50)
        let smallFont = UIFont.systemFont(ofSize: 15)
        
        var body: some View {
            HStack(alignment:.top) {
                Image(systemName: "cloud.drizzle.fill")
                    .background(Color.red)
                    .padding(.top, bigFont.lineHeight-bigFont.ascender)
                HStack(alignment: .firstTextBaseline) {
                    Text("14°")
                        .font(Font(bigFont))
                        .background(Color.blue)
                    
                    Text("86%")
                        .font(Font(smallFont))
                        .baselineOffset((bigFont.capHeight - smallFont.capHeight))
                        .background(Color.yellow)
                    Spacer()
                }
            }
        }
    }
    

    PS : I added backgrounds to show you the real frames of each view