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
.
I want to use SwiftUI
, to achieve
- All 3 images are having same height.
- 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.
CodePudding user response:
Call frame(minWidth:idealWidth:maxWidth:minHeight:idealHeight:maxHeight:alignment:)
and specify maxHeight
. This ways all images will have the same size.
CodePudding user response:
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
CodePudding user response:
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:
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.