11

I was wondering what I would need if I wanted to use a mask image to get my UIImageView in a specific shape. From what I understand, to create a mask, I need to have an image with the shape of the mask all black on top of a white background. Something like this, for example:

Star-shaped mask image

First of all, is this sufficient to shape an image view, and if so, how do I do it in Swift 3? I can only find masking code that is either outdated or written in Objective-C. I've tried simply assigning the image above to an UIImageView and then assign the image view to the mask property of the UIImageView I want to shape, like so:

self.defaultImageView.mask = self.maskImageView

This didn't do anything. It just made self.maskImageView disappear (both image view's added through the storyboard and connected using IBOutlet properties). I'm sure I'm forgetting to do something. It can't be this simple. I would appreciate it if someone could help me out. Like I said, I put both image views on the exact same spot, on top of each other, in the storyboard.

UPDATE: My first attempt to set the mask programmatically after deleting it from my storyboard.

let layer:CALayer = CALayer()
    let mask:UIImage = UIImage(named: "Black-Star-Photographic-Agency")!
    layer.contents = mask
    layer.frame = CGRect(x: 0, y: 0, width: ((self.defaultImageView.image?.size.width)!), height: (self.defaultImageView.image?.size.height)!)
    self.defaultImageView.layer.mask = layer
    self.defaultImageView.layer.masksToBounds = true

The result was that the image view had completely disappeared and wasn't visible anymore. Am I doing something, am I forgetting something or both?

Freddy Benson
  • 735
  • 4
  • 11
  • 30
  • @matt So the only way is to create one on my own? That's gonna be tricky because I have some very complicated shapes I need to turn into masks. – Freddy Benson Oct 22 '16 at 08:47
  • @matt Oh, well you said "opaque and transparent", but you're gonna have to elaborate on that because I have no idea what that means or how to apply that to my mask image view. – Freddy Benson Oct 22 '16 at 08:56
  • @matt so If I turn the (white) background of my mask image transparent, it will work? The only reason I assumed I needed black and white because some bloggers implicitly stated masks are always black and white. Cant find the link right now, though. – Freddy Benson Oct 22 '16 at 09:01
  • 1
    @matt Calm down, you only said it once and that was after I told you to explain what you mean by "opaque and transparent", which was your first comment. If you're gonna answer someone's question, you should at least try to do some explaining of the answer that you're giving, because the fact that I posted my question here should have been a hint that I am not a graphic designer or a freakin' scientist, so my sincere apologies for not being able to decrypt the three words you gave me into full-written instructions. Have a morning decaf, dude, you obviously need it. – Freddy Benson Oct 22 '16 at 09:17

2 Answers2

20

You should use a png image, which supports transparency, unlike jpg.

In Photoshop your image should look similar to this:

enter image description here

It doesn't matter if your shape is black or white. What matters is transparency of each pixel. Opaque area (black in this case) will be visible and transparent area will get trimmed.

Edit:

You should not create mask view from storyboard if you do so. It is not going to be a part of your view hierarchy. Just add it programmatically like this:

let maskView = UIImageView()

override func viewDidLoad() {
    super.viewDidLoad()
    maskView.image = UIImage(named: "mask")
    imageView.mask = maskView        
}

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    maskView.frame = imageView.bounds
}

Output:

enter image description here

Here is a test project to show how it's working.

alexburtnik
  • 7,661
  • 4
  • 32
  • 70
  • 1
    Yeah I thought so. I remember this is the first thing I tried, but then the exact opposite of the mask image (so the transparent part) ended up becoming the mask shape. Must have done something wrong there. I'll give it another shot. Thanks! – Freddy Benson Oct 22 '16 at 09:04
  • It's not working. I used the PNG image with a transparent, made both image views the exact same size, both width and height, but when I assign the mask image view as the mask of my default image view, they both disappear and the the view is just white, with nothing to be seen. What am I doing wrong? – Freddy Benson Oct 22 '16 at 21:16
  • I double checked to make sure the background is completely transparent, and to make sure the shape is completely opaque, but still nothing. – Freddy Benson Oct 22 '16 at 21:17
  • Ok, edit your question with some code to show how mask imageView is created and how it's frame is set. – alexburtnik Oct 22 '16 at 21:22
  • I didn't set any frames programmatically. The only code I used is already in my question. I'm only assigning my mask image view to the mask property, that's it. From your reply, I can guess I forgot to do a bunch of stuff, right? – Freddy Benson Oct 22 '16 at 22:26
  • Try to create mask programmatically. It should not be added as a subview, as you did – alexburtnik Oct 23 '16 at 07:13
  • That's impossible for me to do. Even a simple star or triangle is very difficult, since I've never drawn anything programmatically. Even worse is that the shapes I have are very complicated and detailed and are probably impossible to draw for ANYONE, let alone me. I don't get it, first you said I just need a opaque/transparent image and now you're telling me I shouldn't add it as a subview. So is it possible or not, because right now I'm way more confused than I was before asking this question. – Freddy Benson Oct 23 '16 at 08:04
  • First, you don't need to create shape programmatically, just create imageView with your png, as I posted yesterday in edited answer. Second, you should not add it as a subview (neither programmatically nor from xib/storyboard), all you need is to set `maskView` to `mask` property of `defaultImageView` – alexburtnik Oct 23 '16 at 08:12
  • Oh okay, so should I configure anything else to the mask image view, like size for example, or just add it as the mask the way it is? – Freddy Benson Oct 23 '16 at 08:14
  • Just updated my post with some sample of my first (failed) attempt to set the mask programmatically. Any feedback? – Freddy Benson Oct 23 '16 at 09:44
  • @FreddyBenson Have you actually tried the code I suggested? – alexburtnik Oct 23 '16 at 21:13
  • Yes, the image view completely disappears if I do that. – Freddy Benson Oct 24 '16 at 01:50
  • @FreddyBenson Try once again, I've updated the code sample. This time I've tested it myself and include a working project to make sure it is working as you expect. – alexburtnik Oct 24 '16 at 11:06
  • Thanks! I did everything exactly the way you did it in the test project, but it's still not working, so my best guess is that the image I'm using probably isn't correctly formatted. I'll try it out with a few other PNG images and see if that works. Anyway, thanks for the time and effort you put into making the project. Appreciate it! – Freddy Benson Oct 24 '16 at 14:44
  • How i create/draw a border around the masked image/ UIView? – Gulshan Kumar Oct 08 '19 at 08:07
3

Also if you're using a custom frame/image and run into the mask not showing properly, try setting the content mode of the mask:

maskView.contentMode = .scaleAspectFit
Larry Mickie
  • 441
  • 4
  • 9