5

I can't find a way to make a UIImageView wrapped in a UIViewRepresentable be sized to fit the frame. It always resizes beyond the screen no matter what content Mode or clipping or explcit framing I do. (The image dimensions are much larger than the device screen frame)

To clarify: I need to use UIImageView due to some subview positioning I have to do down the line and various other reasons.

Here's a paired down example:

struct ImageView: UIViewRepresentable {
    
    var image: UIImage
    
    func makeUIView(context: Context) -> some UIView {
    
        let imageView = UIImageView()
        imageView.image = image
        imageView.backgroundColor = .red
        imageView.contentMode = .scaleAspectFit
        imageView.clipsToBounds = true
        imageView.frame = CGRect(x: 0, y: 0, width: 300, height: 400)
        
        return imageView
    }
    
    func updateUIView(_ uiView: UIViewType, context: Context) {
    }
    
}

Then this is how I'm trying to implement it

struct ContentView: View {
    var body: some View {
        ImageView(image: UIImage(named: "full-ux-bg-image")!)
        //.frame(width: 300, height: 400, alignment: .center)  //This is just a test of explicit sizing
            .padding()
    }
}

Any ideas how to make this work? I want it to fit in the SwiftUI view without going over.

santi.gs
  • 514
  • 3
  • 15

1 Answers1

7

It has default constrains for content hugging/compression, to have possibility to manipulate with view externally we need to lowered those (... and never set frame for representable, just in case)

Here is fixed variant (tested with Xcode 14 / iOS 16)

func makeUIView(context: Context) -> some UIView {

    let imageView = UIImageView()
    imageView.image = image
    imageView.backgroundColor = .red
    imageView.contentMode = .scaleAspectFit
    imageView.clipsToBounds = true
    
    imageView.setContentHuggingPriority(.defaultLow, for: .vertical)
    imageView.setContentHuggingPriority(.defaultLow, for: .horizontal)
    imageView.setContentCompressionResistancePriority(.defaultLow, for: .vertical)
    imageView.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)

    return imageView
}
Asperi
  • 228,894
  • 20
  • 464
  • 690