0

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?

2
  • SwiftUI.Layout might be an option Commented Sep 3, 2023 at 15:25
  • Yes, you are probably right. I tries this (see link above), but I could not get it to work. Commented Sep 3, 2023 at 16:22

1 Answer 1

1

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)
                }
            }
        }
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks! Rotating the HStackis indeed the easiest way. I did not think about it. The problem, however, is that rotation is about an anchor point, normally the center. This means that the distance to the border depends on the length of the HStack. I tried to get this distance using a GeometryReader, but failed. But the other suggested methods do work well.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.