skip to Main Content

The following is the screenshots.

The left iPhone, where there are 3 images in a single row, are having same height and correct aspect ratio. It is implemented using UIKit.

The right iPhone, where there are 3 images in a single row, are having different height and correct aspect ratio. It is implemented using SwiftUI.

enter image description here

I want to use SwiftUI, to achieve

  1. All 3 images are having same height.
  2. All 3 images are having correct aspect ratio.

In UIKit, this is how I achieve so

Step 1: Use a horizontal stack view

let horizontalStackView = UIStackView()

horizontalStackView.axis = .horizontal
horizontalStackView.distribution = .fill
horizontalStackView.alignment = .fill
horizontalStackView.spacing = spacing

Step 2: Assign correct constraint to every UIImageView based on original image dimension

let imageView = UIImageView()
imageView.contentMode = .scaleAspectFit

let multiplier = CGFloat((Double)(attachment.height) / (Double)(attachment.width))
imageView.heightAnchor.constraint(
    equalTo: imageView.widthAnchor,
    multiplier: multiplier).isActive = true

However, I am not sure how I can implement similar idea in SwiftUI. So far, this is how I achieve imperfect outcome at the right iPhone screenshot. They are having correct aspect ratio. But they are not having same height.

SwiftUI, incorrect outcome

struct ContentView: View {
    var body: some View {
        HStack {
            VStack(alignment: .leading, spacing: 4) {
                HStack(spacing: 2) {
                    Image("0").resizable().aspectRatio(contentMode: .fit)
                    
                    Image("3").resizable().aspectRatio(contentMode: .fit)
                    
                    Image("2").resizable().aspectRatio(contentMode: .fit)
                }
                Text("Hello, world!")
                
                Spacer(minLength: 0)
            }
            
            Spacer(minLength: 0)
        }
    }
}

Do you have idea, how I can achieve the same outcome in SwiftUI, as I did in UIKit? Thanks.

3

Answers


  1. Call frame(minWidth:idealWidth:maxWidth:minHeight:idealHeight:maxHeight:alignment:) and specify maxHeight. This ways all images will have the same size.

    Login or Signup to reply.
  2. define aspect ratio same for all images, like this:

     HStack(spacing: 2) {
                            
                            Image("0").resizable().aspectRatio(CGSize(width: 3, height: 3), contentMode: .fit)
                            
                            Image("1").resizable().aspectRatio(CGSize(width: 3, height: 3),contentMode: .fit)
                            
                            Image("2").resizable().aspectRatio(CGSize(width: 3, height: 3),contentMode: .fit)
                        }
    

    you will get the desired output

    Login or Signup to reply.
  3. This seems to match what you did on UIKit with similar results. That is, using .fill on the images, restricting the horizontal stack to a fixed size and then calculating the HStack’s height based on the device’s width multiplied by the aspect ratio of the desired HStack.

    This is the original code with changes:

    struct ContentView: View {
        var body: some View {
            HStack {
                VStack(alignment: .leading, spacing: 4) {
                    HStack(spacing: 2) {
                        Image("0").resizable().aspectRatio(contentMode: .fill)
                        Image("3").resizable().aspectRatio(contentMode: .fill)
                        Image("2").resizable().aspectRatio(contentMode: .fill)
                    }
                    .fixedSize(horizontal: true, vertical: false)
                    .frame(height: UIScreen.main.bounds.size.width * (2.1 / 7))
                    
                    Text("Hello, world!").padding(.leading)
                    
                    Spacer(minLength: 0)
                }
                
                Spacer(minLength: 0)
            }
        }
    }
    

    The result for an iphone and an ipad:

    enter image description here
    enter image description here

    The .aspectRatio doesn’t appear to work on an HStack so I used frame() instead. The magic number is a guestimate using the image of your desired layout (height / width). To match the original image, .padding(.leading) was also added.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search