cowbjt
cowbjt

Reputation: 263

How to set UIImageView with rounded corners for aspect fit mode

I usually use the following code to set rounded corners.

imageView.layer.cornerRadius = 10

It works when the imageView is set at Aspect Fill.

But when the imageView is set to Aspect Fit mode, and the ratio between imageView and picture are different. The rounded corners effect won't be able to tell.

enter image description here

The background color is set to green for showing the rounded corners.

Is there any way to set 'real image part' to rounded corners.

Thank you in advance for your answers.

Upvotes: 26

Views: 17492

Answers (9)

regina_fallangi
regina_fallangi

Reputation: 2198

Here a solution using the recommended renderer UIGraphicsImageRenderer:

extension UIImageView {
    func setRoundedCorners(radius: CGFloat) {
        guard let image = self.image else {
            fatalError("Set image first")
        }
        let imageLayer = CALayer()
        imageLayer.frame = CGRectMake(0, 0, image.size.width, image.size.height)
        imageLayer.contents = image.cgImage
        imageLayer.masksToBounds = true
        imageLayer.cornerRadius = radius
        
        let renderer = UIGraphicsImageRenderer(
            bounds: CGRectMake(0, 0, image.size.width, image.size.height),
            format:  UIGraphicsImageRendererFormat(for: traitCollection)
        )
        let roundedImage = renderer.image { action in
            imageLayer.render(in: action.cgContext)
        }
        
        self.image = roundedImage
    }
}

Then you can just do:

let imageView = UIImageView(image: <your image>)
imageView. setRoundedCorners(radius: 16)

Upvotes: 0

Levan Karanadze
Levan Karanadze

Reputation: 461

If you use SDWebImage in your project, you can do the following:

myUIImageView.image = myUIImage.sd_roundedCornerImage(withRadius: 24, corners: .allCorners, borderWidth: 0, borderColor: nil)

Upvotes: 0

ordosalutis
ordosalutis

Reputation: 31

I wanted to comment on Arun's answer to help those who are having issues with doing Arun's method but in Collection View, you have to initiate the imageView's frame as the collection view cell's frame.

i.e.

let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "identifier", for: indexPath) as UICollectionViewCell
let imageView = UIImageView(frame: cell.frame)

obviously you want to refactor that and stuff but you get the idea.

Upvotes: 0

OffensivelyBad
OffensivelyBad

Reputation: 801

This is the accepted answer converted to Objective-C:

@implementation UIImageView(Utils)

- (void)roundCornersForAspectFitWithRadius:(CGFloat)cornerRadius {
    if (self.image) {
        double boundsScale = self.bounds.size.width / self.bounds.size.height;
        double imageScale = self.image.size.width / self.image.size.height;

        CGRect drawingRect = self.bounds;

        if (boundsScale > imageScale) {
            drawingRect.size.width = drawingRect.size.height * imageScale;
            drawingRect.origin.x = (self.bounds.size.width - drawingRect.size.width) / 2;
        }
        else {
            drawingRect.size.height = drawingRect.size.width / imageScale;
            drawingRect.origin.y = (self.bounds.size.height - drawingRect.size.height) / 2;
        }
        UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:drawingRect cornerRadius:cornerRadius];
        CAShapeLayer *mask = [CAShapeLayer new];
        [mask setPath:path.CGPath];
        [self.layer setMask:mask];
    }
}

@end

Upvotes: 2

Rajender Kumar
Rajender Kumar

Reputation: 1377

This is very simple to round the image view like this:

self.profileImageView?.clipsToBounds = true
self.profileImageView!.layer.cornerRadius = 10
self.profileImageView?.layer.borderWidth = 1.0
self.profileImageView?.contentMode = .ScaleAspectFit

But for making image view rounded with image ratio, I think you have to set image view for ScaleAspectFill mode.

Upvotes: -3

Aruna Mudnoor
Aruna Mudnoor

Reputation: 4825

Use this extension to UIImageView:

extension UIImageView
{
    func roundCornersForAspectFit(radius: CGFloat)
    {
        if let image = self.image {

            //calculate drawingRect
            let boundsScale = self.bounds.size.width / self.bounds.size.height
            let imageScale = image.size.width / image.size.height

            var drawingRect: CGRect = self.bounds

            if boundsScale > imageScale {
                drawingRect.size.width =  drawingRect.size.height * imageScale
                drawingRect.origin.x = (self.bounds.size.width - drawingRect.size.width) / 2
            } else {
                drawingRect.size.height = drawingRect.size.width / imageScale
                drawingRect.origin.y = (self.bounds.size.height - drawingRect.size.height) / 2
            }
            let path = UIBezierPath(roundedRect: drawingRect, cornerRadius: radius)
            let mask = CAShapeLayer()
            mask.path = path.cgPath
            self.layer.mask = mask
        }
    }
}

Without calling this function

After calling this extension method

Upvotes: 48

amagain
amagain

Reputation: 2072

Swift 3 version of the helpful, accepted answer is over here!

extension UIImageView {
func roundCornersForAspectFit(radius: CGFloat)
{
    if let image = self.image {

        //calculate drawingRect
        let boundsScale = self.bounds.size.width / self.bounds.size.height
        let imageScale = image.size.width / image.size.height

        var drawingRect : CGRect = self.bounds

        if boundsScale > imageScale {
            drawingRect.size.width =  drawingRect.size.height * imageScale
            drawingRect.origin.x = (self.bounds.size.width - drawingRect.size.width) / 2
        }else {
            drawingRect.size.height = drawingRect.size.width / imageScale
            drawingRect.origin.y = (self.bounds.size.height - drawingRect.size.height) / 2
        }
        let path = UIBezierPath(roundedRect: drawingRect, cornerRadius: radius)
        let mask = CAShapeLayer()
        mask.path = path.cgPath
        self.layer.mask = mask
        }
    }
}

Upvotes: 5

Dipak Chhag
Dipak Chhag

Reputation: 149

You first need to set the width and height to the same value. Then set the image properties like so:

imgProfile_Pic.layer.cornerRadius = cell.imgProfile_Pic.frame.size.height / 2
imgProfile_Pic.layer.borderWidth = 3.0
imgProfile_Pic.layer.borderColor = UIColor.white.cgColor
imgProfile_Pic.clipsToBounds = true
imgProfile_Pic.layoutIfNeeded()

Upvotes: 1

technerd
technerd

Reputation: 14504

Try this may help you:

import UIKit


class ViewController: UIViewController{

    @IBOutlet weak var myImageView: UIImageView!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        myImageView.contentMode = UIViewContentMode.ScaleAspectFit
        myImageView.clipsToBounds = true
        //myImageView.layer.cornerRadius = 10.0
        myImageView.layer.masksToBounds = true

        let simpleImage = UIImage(named:"ipad5_einladung.jpg")
        let corneredImage = generateRoundCornerImage(simpleImage!, radius: 10)

        //Set cornered Image
        myImageView.image = corneredImage;

    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


    func generateRoundCornerImage(image : UIImage , radius : CGFloat) -> UIImage {

        let imageLayer = CALayer()
        imageLayer.frame = CGRectMake(0, 0, image.size.width, image.size.height)
        imageLayer.contents = image.CGImage
        imageLayer.masksToBounds = true
        imageLayer.cornerRadius = radius

        UIGraphicsBeginImageContext(image.size)
        imageLayer.renderInContext(UIGraphicsGetCurrentContext())
        let roundedImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return roundedImage
    }

}

Upvotes: 3

Related Questions