skip to Main Content

enter image description here

Here I have attached the screenshot that I have worked. I am facing an issue that image view is not scaling to the frame. I have created a custom view within the custom view i have added imageview and set constraints to its parent view (here containerview)

image content mode is scaleAspectFit

let imageView = makeImageView()
addSubview(imageView)

imageView.topAnchor.constraint(equalTo: topAnchor).isActive = true
imageView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
imageView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
imageView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true

When I initialise the custom view into the viewcontroller shows like above screenshots. In viewcontroller I am just adding the image to the stackview.

Can you please let me know what should be added?

2

Answers


  1. You may set the following properties to scale the size of the UIImageView as per the image size –

    imgView.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)
    
    imgView.setContentCompressionResistancePriority(.defaultHigh, for: .vertical)
    
    
    Login or Signup to reply.
  2. You need to leave the image view’s content mode set to .contentMode = .scaleToFill.

    Then, when you set its .image, set a proportional height anchor with:

    multiplier: img.size.height / img.size.width)
    

    Here is an example custom class – I’ve inset the image view by 8-points on all 4 sides for clarity:

    class ProportionalImageView: UIView {
        
        public var image: UIImage? {
            didSet {
                imgView.image = image
                if let img = image {
                    proConstraint.isActive = false
                    proConstraint = imgView.heightAnchor.constraint(equalTo: imgView.widthAnchor, multiplier: img.size.height / img.size.width)
                    proConstraint.isActive = true
                }
            }
        }
        
        private var proConstraint: NSLayoutConstraint!
        
        private let imgView = UIImageView()
    
        override init(frame: CGRect) {
            super.init(frame: frame)
            commonInit()
        }
        required init?(coder: NSCoder) {
            super.init(coder: coder)
            commonInit()
        }
        private func commonInit() {
    
            imgView.contentMode = .scaleToFill
            imgView.translatesAutoresizingMaskIntoConstraints = false
            addSubview(imgView)
        
            proConstraint = imgView.heightAnchor.constraint(equalTo: imgView.widthAnchor, multiplier: 1.0)
            
            NSLayoutConstraint.activate([
                imgView.topAnchor.constraint(equalTo: topAnchor, constant: 8.0),
                imgView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 8.0),
                imgView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -8.0),
                imgView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -8.0),
                proConstraint,
            ])
            
            backgroundColor = .systemBlue
        }
        
    }
    

    and an example view controller… vertical stack view containing a "top label" the custom view and a "bottom label". Also loads 3 images – at 300×300, 300×200 and 200×300. Tapping anywhere cycles through to the next image:

    class ProImageTestVC: UIViewController {
        
        let proImageView = ProportionalImageView()
        
        var images: [UIImage] = []
        
        override func viewDidLoad() {
            super.viewDidLoad()
            
            ["i300x300", "i200x300", "i300x200"].forEach { sName in
                guard let img = UIImage(named: sName) else {
                    fatalError("Could not load image: (sName)")
                }
                images.append(img)
            }
            
            let stackView = UIStackView()
            stackView.axis = .vertical
        
            let v1 = UILabel()
            v1.text = "Top Label"
            v1.textAlignment = .center
            v1.backgroundColor = .green
            
            let v2 = UILabel()
            v2.text = "Bottom Label"
            v2.textAlignment = .center
            v2.backgroundColor = .green
            
            stackView.addArrangedSubview(v1)
            stackView.addArrangedSubview(proImageView)
            stackView.addArrangedSubview(v2)
    
            stackView.translatesAutoresizingMaskIntoConstraints = false
            view.addSubview(stackView)
            
            let g = view.safeAreaLayoutGuide
            NSLayoutConstraint.activate([
                stackView.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
                stackView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 60.0),
                stackView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -60.0),
            ])
            
            nextImage()
        }
    
        func nextImage() {
            let img = images.removeFirst()
            images.append(img)
            proImageView.image = img
        }
        override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
            nextImage()
        }
        
    }
    

    Using these three images:

    enter image description here

    enter image description here

    enter image description here

    It looks like this when running:

    enter image description here

    enter image description here

    enter image description here

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