How to display vertically an array of turned images in SwiftUI?

105 Views Asked by At

My app has an array hand of a struct with a property let blatt: Image. During init, an Image is assigned to this property.

To display such an array horizontally, I use the following code (scaledWidth is some constant):

HStack(spacing: 10) {
    ForEach((0 ..< hand.count), id: \.self) {
        hand[$0].blatt
            .resizable()
            .scaledToFit() 
            .frame(height: scaledWidth)
            .border(.black)
    }
}

This gives the following output:

enter image description here

This is what I expected.

Another array is to be displayed vertically. For this, I am using the following code:

VStack(spacing: 10) {
    ForEach((0 ..< hand.count), id: \.self) {
        hand[$0].blatt
            .resizable()
            .scaledToFit() 
            .rotationEffect(Angle(degrees: 90))
            .frame(width: scaledWidth, height: scaledWidth)
            .border(.black)
    }
}

This gives additionally the following output:

enter image description here

Here, the height of each frame, as indicated by the bordered frame, is the height of the unrotated image.

Since I know the aspect ratio aspectRatioBlatt of the images, I can adjust the output using .frame(width: scaledWidth, height: scaledWidth / aspectRatioBlatt). Then, the frames have the correct dimensions and the correct spacing, but the images inside are too little. Again, the height of the frame is then equal to the height of the inner unrotated image.

I have tried many view modifiers and multiple combinations, but failed. I even tried to use a custom layout as suggested here for vertical Text, but this did not work either.
Of course I could use a 2nd set of turned images, but it should be possible without it in SwiftUI.

How to do it right?

1

There are 1 best solutions below

1
Benzy Neez On BEST ANSWER

It might be simplest to rotate the HStack instead.

Otherwise, if you know the aspect ratio then you can set the frame size before rotation and then adjust the height after rotation:

struct ContentView: View {

    let width = CGFloat(50)
    let aspectRatio = 31.0 / 15.0
    let colors: [Color] = [.green, .blue, .mint, .teal, .purple]

    var body: some View {
        VStack(spacing: 50) {
            HStack(spacing: 10) {
                ForEach((0 ..< colors.count), id: \.self) { index in
                    Image(systemName: "figure.wave")
                        .resizable()
                        .scaledToFit()
                        .frame(width: width, height: width * aspectRatio)
                        .background { colors[index] }
                        .border(.black)
                }
            }
            VStack(spacing: 10) {
                ForEach((0 ..< colors.count), id: \.self) { index in
                    Image(systemName: "figure.wave")
                        .resizable()
                        .scaledToFit()
                        .frame(width: width, height: width * aspectRatio)
                        .background { colors[index] }
                        .border(.black)
                        .rotationEffect(.degrees(90))
                        .frame(height: width)
                }
            }
        }
    }
}

RotatedImages

I found it also worked by setting only the width and then using scaledToFill:

struct ContentView: View {

    let width = CGFloat(50)
    let colors: [Color] = [.green, .blue, .mint, .teal, .purple]

    var body: some View {
        VStack(spacing: 50) {
            HStack(spacing: 10) {
                ForEach((0 ..< colors.count), id: \.self) { index in
                    Image(systemName: "figure.wave")
                        .resizable()
                        .scaledToFit()
                        .frame(width: width)
                        .background { colors[index] }
                        .border(.black)
                }
            }
            VStack(spacing: 10) {
                ForEach((0 ..< colors.count), id: \.self) { index in
                    Image(systemName: "figure.wave")
                        .resizable()
                        .scaledToFill()
                        .frame(width: width)
                        .background { colors[index] }
                        .border(.black)
                        .rotationEffect(.degrees(90))
                        .frame(height: width)
                }
            }
        }
    }
}