2

I have a UIImageView and i'd like to make a circular region in the centre of the image view transparent so that when an image is passed to the image view, the image seems to cover all of the image view except for the centre.

Here's what i currently have Instead of that black circle in the image, I want to see the background.

There is a similar question here but I need someone to show me how to do it in code as I don't really know Core Graphics.

Any help would be greatly appreciated.

Community
  • 1
  • 1
SasukeIsCool
  • 227
  • 4
  • 11
  • Why wouldn't you just use a PNG image with the hole transparent? – picciano Jul 14 '14 at 20:26
  • Because I'm pulling the images from a foreign website. I don't have access to the images, just the URLs – SasukeIsCool Jul 14 '14 at 20:30
  • 1
    Ah, in that case, see this answer on how to create mask. http://stackoverflow.com/questions/5757386/how-to-mask-an-uiimageview – picciano Jul 14 '14 at 20:33
  • Will the mask need to be of the exact same size as the image? – SasukeIsCool Jul 14 '14 at 20:43
  • Core graphics IS code. There is no other way to do this other than getting images with a transparent centre in the first place. That would be easiest. – Fogmeister Jul 14 '14 at 20:43
  • The mask will need to be the same size as the UIImageView that you are using to display the image. The image might be 300x300 but if you're displaying it at 50x50 then the mask needs to be 50x50. – Fogmeister Jul 14 '14 at 20:44
  • I'd prefer to do it in code. But i guess this is cool too. Any suggestions on how to create a mask? – SasukeIsCool Jul 14 '14 at 20:50

2 Answers2

4

This will do:

UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(50.0, 50.0, 100.0, 100.0)];
[imageView setBackgroundColor:[UIColor redColor]];

UIBezierPath *maskPath = [UIBezierPath bezierPathWithOvalInRect:imageView.bounds];

UIBezierPath *holePath = [UIBezierPath bezierPathWithOvalInRect:CGRectInset(imageView.bounds, 35.0, 35.0)];
[maskPath appendPath:holePath];

CAShapeLayer *mask = [CAShapeLayer layer];
[mask setFillRule:kCAFillRuleEvenOdd];
mask.path = maskPath.CGPath;

[imageView.layer setMask:mask];

[self.view addSubview:imageView];

The more inset you give the 'holePath' the smaller the radius of the inner circle ;)

CodingMeSwiftly
  • 3,231
  • 21
  • 33
  • No problem :) It looks like you are going to use the imageView in a tableView ? if so - the masking may be bad for scroll performance. To solve this, set 'shouldRasterize' of the imageView's layer to YES & set the 'rasterizationScale' to '[UIScreen mainScreen].scale' – CodingMeSwiftly Jul 14 '14 at 20:57
  • Its a search function and I limited the number of search results to 10 so the table view is barely scrollable so the overhead isn't noticed. But thanks for the heads up. I'll definitely take note of that for future use. – SasukeIsCool Jul 14 '14 at 21:07
0

Swift 5

let maskPath = UIBezierPath(ovalIn: albumImageView.bounds)
    let holePath = UIBezierPath(ovalIn: albumImageView.bounds.insetBy(dx: 30,dy: 30))
    maskPath.append(holePath)
    let mask = CAShapeLayer()
    mask.fillRule = .evenOdd
    mask.path = maskPath.cgPath
    albumImageView.layer.mask = mask