I have an image which has contentMode set to scaleAspectFit with a cornerRadius but i don't get the rounded corner but when I set the contentMode to scaleAspectFill it works. My question is i still need my contentMode to be set to scaleAspectFit and also have my cornerRadius show. Below is my sample code.
private let imageView: UIImageView = {
let image = UIImageView()
image.translatesAutoresizingMaskIntoConstraints = false
image.clipsToBounds = true
image.image = UIImage(named: "105")
image.layer.cornerRadius = 30
image.contentMode = .scaleAspectFit
return image
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .systemBackground
setUpConstraints()
}
private func setUpConstraints(){
view.addSubview(btnClose)
view.addSubview(lblRateIT)
view.addSubview(lblLoveIT)
view.addSubview(redBottomView)
view.addSubview(imageView)
NSLayoutConstraint.activate([
imageView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 50),
imageView.topAnchor.constraint(equalTo: lblLoveIT.bottomAnchor, constant: 20),
imageView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -50),
imageView.bottomAnchor.constraint(equalTo: redBottomView.topAnchor, constant: -20)
])
}
CodePudding user response:
Without knowing what else you might be wanting to do with this, the most straight-forward approach is to use constraints that match the aspect ratio of the image itself.
So, we can:
- create a "container"
UIView
to hold the imageView - constrain the image view to max width and height of the container
- center the image view in the container
- constrain the height of the image view equal to the width of the image view, with a multiplier of
image.size.height / image.size.width
Using these 3 sample images - horizontal / square / vertical:
and this example view controller:
class ViewController: UIViewController {
let imageOptions: [String] = ["Horizontal", "Square", "Vertical"]
lazy var segCtrl = UISegmentedControl(items: imageOptions)
let imgView = UIImageView()
// "container" for the image view
let imgContainerView = UIView()
// we'll modify this when we change the image
var aspectConstraint: NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .systemBackground
imgView.contentMode = .scaleAspectFit
imgView.layer.cornerRadius = 30.0
imgView.layer.masksToBounds = true
imgContainerView.backgroundColor = .yellow
segCtrl.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(segCtrl)
imgContainerView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(imgContainerView)
imgView.translatesAutoresizingMaskIntoConstraints = false
imgContainerView.addSubview(imgView)
let g = view.safeAreaLayoutGuide
// make image view as wide and as tall as possible
// fitting in the targetRectView
// and using aspect ratio of the UIImage
let ivW = imgView.widthAnchor.constraint(equalTo: imgContainerView.widthAnchor)
ivW.priority = .required - 1
let ivH = imgView.heightAnchor.constraint(equalTo: imgContainerView.heightAnchor)
ivH.priority = .required - 1
// we haven't loaded an image yet, so let's start with 1:1
aspectConstraint = imgView.heightAnchor.constraint(equalTo: imgView.widthAnchor, multiplier: 1.0)
NSLayoutConstraint.activate([
segCtrl.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
segCtrl.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
segCtrl.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
segCtrl.heightAnchor.constraint(equalToConstant: 40.0),
// let's put the container view below the segmented control
// with 60-points "padding" on all 4 sides
imgContainerView.topAnchor.constraint(equalTo: segCtrl.bottomAnchor, constant: 60.0),
imgContainerView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 60.0),
imgContainerView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -60.0),
imgContainerView.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: -60.0),
imgView.centerXAnchor.constraint(equalTo: imgContainerView.centerXAnchor),
imgView.centerYAnchor.constraint(equalTo: imgContainerView.centerYAnchor),
imgView.widthAnchor.constraint(lessThanOrEqualTo: imgContainerView.widthAnchor),
imgView.heightAnchor.constraint(lessThanOrEqualTo: imgContainerView.heightAnchor),
ivW, ivH, aspectConstraint,
])
segCtrl.addTarget(self, action: #selector(segChanged(_:)), for: .valueChanged)
}
@objc func segChanged(_ segC: UISegmentedControl) {
updateImage()
}
func updateImage() {
let idx = segCtrl.selectedSegmentIndex
let imgName: String = "sample" imageOptions[idx]
guard let img = UIImage(named: imgName) else {
fatalError("Could not load image: \(imgName)")
}
imgView.image = img
// we need to update the aspect ratio height constraint
aspectConstraint.isActive = false
aspectConstraint = imgView.heightAnchor.constraint(equalTo: imgView.widthAnchor, multiplier: img.size.height / img.size.width)
aspectConstraint.isActive = true
}
}
We get this output at start (no image set):
then for Horizontal / Square / Vertical images:
CodePudding user response:
When you aspectFit
the content mode
of the image, swift fits the image into the imageview in a way that preserves all the proportions. When you give an extra corner radius, the imageview is out of rectangular shape, so it can't fit the photo proportionally. Therefore, contentMode aspectFit can give corner radius values as much as it can fit the screen by preserving the proportions of the photo it is.
Briefly , you can think contentMode = .aspectFit
priority is bigger than cornerRadius
.it can give cornerRadius again, but this will be as much as the amount of space left after the photo fits into the component proportionally.
For example, let's say 5 units. In this case, if you give the cornerRadius
at 5 or 1000, it will remain as 5 units.
In summary , it will not be healthy to use cornerRadius and aspectFit together. I recommend you to change contentMode to scaleAspectFill