Home > Back-end >  Align heights of HStack members
Align heights of HStack members

Time:09-25

I want to align the heights of two HStack members. The expected outcome would be that the image has the same size as the text. The current outcome is that the image has more height than the text. This is my current setup:

HStack {
  Text("Sample")
    .font(.largeTitle)
    .padding()
    .background(
      RoundedRectangle(cornerRadius: 10)
        .foregroundColor(.red)
    )

  Spacer()
      
  Image(systemName: "checkmark.seal.fill")
    .resizable()
    .scaledToFit()
    .padding()
    .background(
      RoundedRectangle(cornerRadius: 10)
        .foregroundColor(.red)
    )
}

What I've tried:

  1. .fixedSize() -> I tried to tack this modifier onto the Image but the result was that the Image's height got smaller than the text's. Probably because the SFSymbol's intrinsic height is smaller than the .largeTitle intrinsic height.
  2. AlignmentGuide -> I tried to create a custom alignment guide where I initially thought I could say "align bottom of Image and Text and align top of Image and Text" and therefore have the same height. But it seemed like you can only apply a single alignment guide per stack view.
  3. GeometryReader -> I tried to wrap the HStack in a GeometryReader in which I tacked the .frame(height: proxy.frame.height) view modifier on the Text and Image. This also did not help because it somehow just made some white space around the views.

How it is:

enter image description here

How I want it:

enter image description here

CodePudding user response:

Wrap your Image in a Text. Since your image is from SF Symbols, SwiftUI will scale it to match the dynamic type size. (I'm not sure how it will scale other images.)

VStack {
    let background = RoundedRectangle(cornerRadius: 10)
        .foregroundColor(.red)

    ForEach(Font.TextStyle.allCases, id: \.self) { style in
        HStack {
            Text("\(style)" as String)
                .padding()
                .background(background)

            Spacer()

            Text(Image(systemName: "checkmark.seal.fill"))
                .padding()
                .background(background)
        }
        .font(.system(style))
    }
}

screen shot showing all dynamic type sizes

CodePudding user response:

You can get the size of the Image small by adding a .frame() modifier to your HStack. See the code below,

HStack {
    // Some Content
}
.frame(height: 60) // Interchangeable with frame(maxHeight: 60)

The Result:

enter image description here

For your exact example, I found 60 to be the sweet spot. But if you wanted a more dynamic solution, I'd make a few changes to your code. See the code below.


HStack {
    Text("Sample")
        .font(.largeTitle)
        .frame(maxHeight: .infinity) // force the text to take whatever height given to the Parent View, which is the HStack
        .padding(.horizontal) // Add padding to the Text to the horizontal axis
        .background(
            RoundedRectangle(cornerRadius: 10)
                .foregroundColor(.red)
        )

    Spacer()

    Image(systemName: "checkmark.seal.fill")
        .resizable()
        .scaledToFit()
        .padding()
        .background(
            RoundedRectangle(cornerRadius: 10)
                .foregroundColor(.red)
        )
}
.background(Color.gray)
.frame(height: 100) // Change this value and the embedded Views will fit dynamically

The output will work as shown in the GIF below,

enter image description here

  • Related